mirror of
https://github.com/espruino/Espruino.git
synced 2025-12-08 19:06:15 +00:00
Merge branch 'master' into SMAQ3
This commit is contained in:
commit
c14f207c83
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,6 +9,7 @@
|
||||
*.srec
|
||||
*.bin
|
||||
*.pyc
|
||||
/*.bin.unpadded
|
||||
/*.zip
|
||||
/gen/*
|
||||
/.vagrant/*
|
||||
|
||||
@ -8,6 +8,13 @@
|
||||
WIZNet: add setHostname(), geHostname(), getStatus()
|
||||
Fix XON not sent after reset() (fix #1872)
|
||||
Remove USBSERIAL enum for non-USB devices
|
||||
Shrink new vector font sizes to allow multi-line use (fix #1873)
|
||||
Stop Object.setPrototypeOf overwriting Object.prototype sometimes (fix #1875)
|
||||
Arrow functions now always overwrite `this` (fix #1878)
|
||||
Implement Streaming Storage compaction to allow compact with less RAM (fix #1598,#1707,#1828)
|
||||
jslTokenAsString now works for 'of'
|
||||
Speed up Array.prototype.join (fix #1660)
|
||||
Allow 'in' to be used with typed arrays (fix #1534)
|
||||
|
||||
2v06 : Allow `"ram"` keyword at the top of a function to allow it to be pretokenised and loaded to RAM
|
||||
Don't store line numbers for pretokenised functions
|
||||
|
||||
@ -1084,7 +1084,7 @@ void jswrap_banglejs_setLCDTimeout(JsVarFloat timeout) {
|
||||
"name" : "setPollInterval",
|
||||
"generate" : "jswrap_banglejs_setPollInterval",
|
||||
"params" : [
|
||||
["interval","float","Polling interval in milliseconds"]
|
||||
["interval","float","Polling interval in milliseconds (Default is 80ms - 12.5Hz to match accelerometer)"]
|
||||
],
|
||||
"ifdef" : "BANGLEJS"
|
||||
}
|
||||
@ -2136,22 +2136,32 @@ void jswrap_banglejs_accelWr(JsVarInt reg, JsVarInt data) {
|
||||
"name" : "accelRd",
|
||||
"generate" : "jswrap_banglejs_accelRd",
|
||||
"params" : [
|
||||
["reg","int",""]
|
||||
["reg","int",""],
|
||||
["cnt","int","If specified, `accelRd` returns and array of the given length (max 128). If not (or 0) it returns a number"]
|
||||
],
|
||||
"return" : ["int",""],
|
||||
"return" : ["JsVar",""],
|
||||
"ifdef" : "BANGLEJS"
|
||||
}
|
||||
Reads a register from the KX023 Accelerometer
|
||||
|
||||
**Note:** On Espruino 2v06 and before this function only returns a number (`cnt` is ignored).
|
||||
*/
|
||||
int jswrap_banglejs_accelRd(JsVarInt reg) {
|
||||
JsVar *jswrap_banglejs_accelRd(JsVarInt reg, JsVarInt cnt) {
|
||||
#ifndef EMSCRIPTEN
|
||||
unsigned char buf[1];
|
||||
if (cnt<0) cnt=0;
|
||||
unsigned char buf[128];
|
||||
if (cnt>sizeof(buf)) cnt=sizeof(buf);
|
||||
buf[0] = (unsigned char)reg;
|
||||
i2cBusy = true;
|
||||
jsi2cWrite(ACCEL_I2C, ACCEL_ADDR, 1, buf, true);
|
||||
jsi2cRead(ACCEL_I2C, ACCEL_ADDR, 1, buf, true);
|
||||
jsi2cRead(ACCEL_I2C, ACCEL_ADDR, cnt, buf, true);
|
||||
i2cBusy = false;
|
||||
return buf[0];
|
||||
if (cnt) {
|
||||
JsVar *ab = jsvNewArrayBufferWithData(cnt, buf);
|
||||
JsVar *d = jswrap_typedarray_constructor(ARRAYBUFFERVIEW_UINT8, ab,0,0);
|
||||
jsvUnLock(ab);
|
||||
return d;
|
||||
} else return jsvNewFromInteger(buf[0]);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
@ -34,7 +34,7 @@ JsVar *jswrap_banglejs_getAccel();
|
||||
|
||||
JsVar *jswrap_banglejs_dbg();
|
||||
void jswrap_banglejs_accelWr(JsVarInt reg, JsVarInt data);
|
||||
int jswrap_banglejs_accelRd(JsVarInt reg);
|
||||
JsVar *jswrap_banglejs_accelRd(JsVarInt reg, JsVarInt cnt);
|
||||
void jswrap_banglejs_compassWr(JsVarInt reg, JsVarInt data);
|
||||
void jswrap_banglejs_ioWr(JsVarInt mask, bool on);
|
||||
JsVar *jswrap_banglejs_project(JsVar *latlong);
|
||||
|
||||
@ -366,7 +366,7 @@ Called with discovered characteristics when discovery is finished
|
||||
"type" : "event",
|
||||
"class" : "NRF",
|
||||
"name" : "NFCon",
|
||||
"ifdef" : "NRF52"
|
||||
"#if" : "defined(NRF52) && defined(USE_NFC)"
|
||||
}
|
||||
Called when an NFC field is detected
|
||||
*/
|
||||
@ -374,7 +374,7 @@ Called when an NFC field is detected
|
||||
"type" : "event",
|
||||
"class" : "NRF",
|
||||
"name" : "NFCoff",
|
||||
"ifdef" : "NRF52"
|
||||
"#if" : "defined(NRF52) && defined(USE_NFC)"
|
||||
}
|
||||
Called when an NFC field is no longer detected
|
||||
*/
|
||||
@ -385,7 +385,7 @@ Called when an NFC field is no longer detected
|
||||
"params" : [
|
||||
["arr","JsVar","An ArrayBuffer containign the received data"]
|
||||
],
|
||||
"ifdef" : "NRF52"
|
||||
"#if" : "defined(NRF52) && defined(USE_NFC)"
|
||||
}
|
||||
When NFC is started with `NRF.nfcStart`, this is fired
|
||||
when NFC data is received. It doesn't get called if
|
||||
@ -2010,7 +2010,7 @@ void jswrap_ble_setLowPowerConnection(bool lowPower) {
|
||||
"type" : "staticmethod",
|
||||
"class" : "NRF",
|
||||
"name" : "nfcURL",
|
||||
"ifdef" : "NRF52",
|
||||
"#if" : "defined(NRF52) && defined(USE_NFC)",
|
||||
"generate" : "jswrap_nfc_URL",
|
||||
"params" : [
|
||||
["url","JsVar","The URL string to expose on NFC, or `undefined` to disable NFC"]
|
||||
@ -2088,7 +2088,7 @@ void jswrap_nfc_URL(JsVar *url) {
|
||||
"type" : "staticmethod",
|
||||
"class" : "NRF",
|
||||
"name" : "nfcPair",
|
||||
"ifdef" : "NRF52",
|
||||
"#if" : "defined(NRF52) && defined(USE_NFC)",
|
||||
"generate" : "jswrap_nfc_pair",
|
||||
"params" : [
|
||||
["key","JsVar","16 byte out of band key"]
|
||||
@ -2149,7 +2149,7 @@ void jswrap_nfc_pair(JsVar *key) {
|
||||
"type" : "staticmethod",
|
||||
"class" : "NRF",
|
||||
"name" : "nfcAndroidApp",
|
||||
"ifdef" : "NRF52",
|
||||
"#if" : "defined(NRF52) && defined(USE_NFC)",
|
||||
"generate" : "jswrap_nfc_androidApp",
|
||||
"params" : [
|
||||
["app","JsVar","The unique identifier of the given Android App"]
|
||||
@ -2208,7 +2208,7 @@ void jswrap_nfc_androidApp(JsVar *appName) {
|
||||
"type" : "staticmethod",
|
||||
"class" : "NRF",
|
||||
"name" : "nfcRaw",
|
||||
"ifdef" : "NRF52",
|
||||
"#if" : "defined(NRF52) && defined(USE_NFC)",
|
||||
"generate" : "jswrap_nfc_raw",
|
||||
"params" : [
|
||||
["payload","JsVar","The NFC NDEF message to deliver to the reader"]
|
||||
@ -2270,7 +2270,7 @@ void jswrap_nfc_raw(JsVar *payload) {
|
||||
"type" : "staticmethod",
|
||||
"class" : "NRF",
|
||||
"name" : "nfcStart",
|
||||
"ifdef" : "NRF52",
|
||||
"#if" : "defined(NRF52) && defined(USE_NFC)",
|
||||
"generate" : "jswrap_nfc_start",
|
||||
"params" : [
|
||||
["payload","JsVar","Optional 7 byte UID"]
|
||||
@ -2339,7 +2339,7 @@ JsVar *jswrap_nfc_start(JsVar *payload) {
|
||||
"type" : "staticmethod",
|
||||
"class" : "NRF",
|
||||
"name" : "nfcStop",
|
||||
"ifdef" : "NRF52",
|
||||
"#if" : "defined(NRF52) && defined(USE_NFC)",
|
||||
"generate" : "jswrap_nfc_stop",
|
||||
"params" : [ ]
|
||||
}
|
||||
@ -2363,7 +2363,7 @@ void jswrap_nfc_stop() {
|
||||
"type" : "staticmethod",
|
||||
"class" : "NRF",
|
||||
"name" : "nfcSend",
|
||||
"ifdef" : "NRF52",
|
||||
"#if" : "defined(NRF52) && defined(USE_NFC)",
|
||||
"generate" : "jswrap_nfc_send",
|
||||
"params" : [
|
||||
["payload","JsVar","Optional tx data"]
|
||||
|
||||
@ -42,7 +42,6 @@ DSTATUS disk_initialize (
|
||||
{
|
||||
if (drv != 0)
|
||||
return STA_NODISK;
|
||||
//jsDebug("Flash Disk Init %d",drv);
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
@ -76,7 +75,7 @@ DRESULT disk_read (
|
||||
uint16_t size = (uint16_t)(count * FS_SECTOR_SIZE);
|
||||
uint32_t addr = sector * FS_SECTOR_SIZE + fs_flash_base;
|
||||
|
||||
jsDebug("Flash disk_read sector: %d, buff: mem: %d buff: %d len: %d", sector, addr, buff, size);
|
||||
jsDebug(DBG_INFO,"Flash disk_read sector: %d, buff: mem: %d buff: %d len: %d", sector, addr, buff, size);
|
||||
jshFlashRead( buff, addr, size);
|
||||
return RES_OK;
|
||||
}
|
||||
@ -98,7 +97,7 @@ DRESULT disk_write (
|
||||
uint16_t size = (uint16_t)(count * FS_SECTOR_SIZE);
|
||||
uint32_t addr = sector * FS_SECTOR_SIZE + fs_flash_base;
|
||||
|
||||
jsDebug("Flash disk_write sector: %d, buff: mem: %d buff: %d len: %d", sector, addr, buff, size);
|
||||
jsDebug(DBG_INFO,"Flash disk_write sector: %d, buff: mem: %d buff: %d len: %d", sector, addr, buff, size);
|
||||
jshFlashErasePage(addr);
|
||||
jshFlashWrite( (void *)buff, addr,size);
|
||||
|
||||
@ -123,7 +122,7 @@ DRESULT disk_ioctl (
|
||||
switch (ctrl) {
|
||||
case CTRL_SYNC : /// Make sure that no pending write process
|
||||
res = RES_OK;
|
||||
jsDebug("Flash disk_ioctl CTRL_SYNC");
|
||||
jsDebug(DBG_INFO,"Flash disk_ioctl CTRL_SYNC");
|
||||
break;
|
||||
|
||||
case GET_SECTOR_COUNT : // Get number of sectors on the disk (DWORD)
|
||||
|
||||
@ -31,13 +31,3 @@
|
||||
#define FS_FLASH_BASE 0x300000;
|
||||
|
||||
uint8_t flashFatFsInit( uint32_t addr, uint16_t sectors );
|
||||
|
||||
/*
|
||||
#ifndef RELEASE
|
||||
#define jsDebug(fmt,...) jsWarn(fmt,##__VA_ARGS__)
|
||||
#else
|
||||
#define jsDebug(fmt,...)
|
||||
#endif
|
||||
#endif
|
||||
*/
|
||||
#define jsDebug(fmt,...)
|
||||
|
||||
@ -649,7 +649,7 @@ int jswrap_E_flashFatFS(JsVar* options) {
|
||||
if (init) {
|
||||
if ( format ) {
|
||||
uint8_t res = f_mount(&jsfsFAT, "", 0);
|
||||
jsDebug("Formatting Flash");
|
||||
jsDebug(DBG_INFO,"Formatting Flash");
|
||||
res = f_mkfs("", 1, 0); // Super Floppy format, using all space (not partition table)
|
||||
if (res != FR_OK) {
|
||||
jsExceptionHere(JSET_INTERNALERROR, "Flash Formatting error:",res);
|
||||
|
||||
@ -18,8 +18,8 @@
|
||||
const uint8_t vfFirstChar = 33;
|
||||
const uint8_t vfLastChar = 255;
|
||||
#define VF_CHAR_WIDTH 13
|
||||
#define VF_SCALE 12
|
||||
#define VF_OFFSET_Y (-3)
|
||||
#define VF_SCALE 16
|
||||
#define VF_OFFSET_Y (-2)
|
||||
#define VF_CHAR_SPACING 1
|
||||
static const uint8_t vfPolyVerts[] IN_FLASH_MEMORY = {
|
||||
169,171,197,195,
|
||||
|
||||
@ -42,12 +42,6 @@
|
||||
|
||||
#define UNUSED(x) (void)(x)
|
||||
|
||||
#ifndef RELEASE
|
||||
#define jsDebug(format, ...) jsWarn(format, ## __VA_ARGS__)
|
||||
#else
|
||||
#define jsDebug(format, ...) do { } while(0)
|
||||
#endif
|
||||
|
||||
static void sendWifiCompletionCB(
|
||||
JsVar **g_jsCallback, //!< Pointer to the global callback variable
|
||||
char *reason //!< NULL if successful, error string otherwise
|
||||
@ -233,7 +227,7 @@ static char *wifiReasonToString(uint8_t reason) {
|
||||
case WIFI_REASON_UNSUPP_RSN_IE_VERSION:
|
||||
return "REASON_UNSUPP_RSN_IE_VERSION";
|
||||
}
|
||||
jsDebug( "wifiReasonToString: Unknown reason %d", reason);
|
||||
jsDebug(DBG_INFO, "wifiReasonToString: Unknown reason %d", reason);
|
||||
return "Unknown reason";
|
||||
} // End of wifiReasonToString
|
||||
|
||||
@ -413,7 +407,7 @@ static JsVar *getWifiModule() {
|
||||
static int s_retry_num = 0;
|
||||
|
||||
static char *wifiGetEvent(uint32_t event) {
|
||||
jsDebug( "wifiGetEvent: Got event: %d", event);
|
||||
jsDebug(DBG_INFO,"wifiGetEvent: Got event: %d", event);
|
||||
switch(event) {
|
||||
case SYSTEM_EVENT_AP_PROBEREQRECVED:
|
||||
return "#onprobe_recv";
|
||||
@ -442,7 +436,7 @@ switch(event) {
|
||||
case SYSTEM_EVENT_WIFI_READY:
|
||||
break;
|
||||
}
|
||||
jsDebug( "Unhandled wifi event type: %d", event);
|
||||
jsDebug(DBG_INFO, "Unhandled wifi event type: %d", event);
|
||||
return NULL;
|
||||
} // End of wifiGetEvent
|
||||
|
||||
@ -488,12 +482,12 @@ static esp_err_t event_handler(void *ctx, system_event_t *event)
|
||||
* * bssid
|
||||
* * reason
|
||||
*/
|
||||
jsDebug("Wifi: Event(%d):SYSTEM_EVENT_%s\n",event->event_id,wifiEventToString(event->event_id));
|
||||
jsDebug(DBG_INFO,"Wifi: Event(%d):SYSTEM_EVENT_%s\n",event->event_id,wifiEventToString(event->event_id));
|
||||
|
||||
if (event->event_id == SYSTEM_EVENT_STA_DISCONNECTED) {
|
||||
if (--s_retry_num > 0 ) {
|
||||
esp_wifi_connect();
|
||||
jsDebug("retry to AP connect");
|
||||
jsDebug(DBG_INFO,"retry to AP connect");
|
||||
return;
|
||||
}
|
||||
g_isStaConnected = false; // Flag as disconnected
|
||||
@ -578,7 +572,7 @@ static esp_err_t event_handler(void *ctx, system_event_t *event)
|
||||
jsvObjectSetChildAndUnLock(jsDetails, "netmask", jsvNewFromString(temp));
|
||||
sprintf(temp, IPSTR, IP2STR(&event->event_info.got_ip.ip_info.gw));
|
||||
jsvObjectSetChildAndUnLock(jsDetails, "gw", jsvNewFromString(temp));
|
||||
jsDebug("Wifi: About to emit connect!");
|
||||
jsDebug(DBG_INFO, "Wifi: About to emit connect!");
|
||||
sendWifiEvent(event->event_id, jsDetails);
|
||||
// start mDNS
|
||||
const char * hostname;
|
||||
@ -642,7 +636,7 @@ static esp_err_t event_handler(void *ctx, system_event_t *event)
|
||||
sendWifiCompletionCB(&g_jsAPStartedCallback, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
jsDebug("Wifi: event_handler -> NOT HANDLED EVENT: %d", event->event_id );
|
||||
jsDebug(DBG_INFO, "Wifi: event_handler -> NOT HANDLED EVENT: %d", event->event_id );
|
||||
return ESP_OK;
|
||||
} // End of event_handler
|
||||
|
||||
@ -658,7 +652,7 @@ void esp32_wifi_init() {
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
|
||||
|
||||
jsDebug("esp32_wifi_init complete");
|
||||
jsDebug(DBG_INFO, "esp32_wifi_init complete");
|
||||
|
||||
} // End of esp32_wifi_init
|
||||
|
||||
@ -674,7 +668,7 @@ static void sendWifiCompletionCB(
|
||||
JsVar **g_jsCallback, //!< Pointer to the global callback variable
|
||||
char *reason //!< NULL if successful, error string otherwise
|
||||
) {
|
||||
jsDebug("sendWifiCompletionCB");
|
||||
jsDebug(DBG_INFO, "sendWifiCompletionCB");
|
||||
// Check that we have a callback function.
|
||||
if (!jsvIsFunction(*g_jsCallback)){
|
||||
return; // we have not got a function pointer: nothing to do
|
||||
@ -699,7 +693,7 @@ static void sendWifiCompletionCB(
|
||||
* Perform a soft initialization of ESP32 networking.
|
||||
*/
|
||||
void jswrap_esp32_wifi_soft_init() {
|
||||
jsDebug("jswrap_esp32_wifi_soft_init()");
|
||||
jsDebug(DBG_INFO, "jswrap_esp32_wifi_soft_init()");
|
||||
JsNetwork net;
|
||||
networkCreate(&net, JSNETWORKTYPE_ESP32); // Set the network type to be ESP32
|
||||
networkState = NETWORKSTATE_ONLINE; // Set the global state of the networking to be online
|
||||
@ -724,7 +718,7 @@ void jswrap_wifi_disconnect(JsVar *jsCallback) {
|
||||
g_jsDisconnectCallback = jsvLockAgainSafe(jsCallback);
|
||||
|
||||
// Call the ESP-IDF to disconnect us from the access point.
|
||||
jsDebug("Disconnecting.....");
|
||||
jsDebug(DBG_INFO, "Disconnecting.....");
|
||||
// turn off auto-connect
|
||||
esp_wifi_set_auto_connect(false);
|
||||
s_retry_num = 0; // flag so we don't attempt to reconnect
|
||||
@ -758,7 +752,7 @@ void jswrap_wifi_stopAP(JsVar *jsCallback) {
|
||||
}
|
||||
err = esp_wifi_set_mode(mode);
|
||||
if (err != ESP_OK) {
|
||||
jsDebug("jswrap_wifi_stopAP: esp_wifi_set_mode rc=%d(%s)", err,wifiErrorToString(err));
|
||||
jsDebug(DBG_INFO, "jswrap_wifi_stopAP: esp_wifi_set_mode rc=%d(%s)", err,wifiErrorToString(err));
|
||||
}
|
||||
|
||||
if (jsvIsFunction(jsCallback)) {
|
||||
@ -772,7 +766,7 @@ void jswrap_wifi_connect(
|
||||
JsVar *jsCallback
|
||||
) {
|
||||
|
||||
jsDebug("jswrap_wifi_connect: entry");
|
||||
jsDebug(DBG_INFO, "jswrap_wifi_connect: entry");
|
||||
|
||||
// Check that the ssid value isn't obviously in error.
|
||||
if (!jsvIsString(jsSsid)) {
|
||||
@ -821,7 +815,7 @@ jsDebug("jswrap_wifi_connect: entry");
|
||||
}
|
||||
jsvUnLock(jsPassword);
|
||||
} // End of we had options
|
||||
jsDebug("jswrap_wifi_connect: SSID, password, Callback done");
|
||||
jsDebug(DBG_INFO, "jswrap_wifi_connect: SSID, password, Callback done");
|
||||
|
||||
// At this point, we have the ssid in "ssid" and the password in "password".
|
||||
// Perform an esp_wifi_set_mode
|
||||
@ -851,7 +845,7 @@ jsDebug("jswrap_wifi_connect: entry");
|
||||
jsError( "jswrap_wifi_connect: esp_wifi_set_mode: %d(%s), mode=%d", err,wifiErrorToString(err), mode);
|
||||
return;
|
||||
}
|
||||
jsDebug("jswrap_wifi_connect: esi_wifi_set_mode done");
|
||||
jsDebug(DBG_INFO, "jswrap_wifi_connect: esi_wifi_set_mode done");
|
||||
|
||||
// Perform a an esp_wifi_set_config
|
||||
wifi_config_t staConfig;
|
||||
@ -861,17 +855,17 @@ jsDebug("jswrap_wifi_connect: entry");
|
||||
memcpy(staConfig.sta.password, password, sizeof(staConfig.sta.password));
|
||||
staConfig.sta.bssid_set = false;
|
||||
esp_wifi_set_auto_connect(true);
|
||||
jsDebug("jswrap_wifi_connect: esp_wifi_set_autoconnect done");
|
||||
jsDebug(DBG_INFO, "jswrap_wifi_connect: esp_wifi_set_autoconnect done");
|
||||
|
||||
err = esp_wifi_set_config(ESP_IF_WIFI_STA, &staConfig);
|
||||
if (err != ESP_OK) {
|
||||
jsError( "jswrap_wifi_connect: esp_wifi_set_config: %d(%s)", err,wifiErrorToString(err));
|
||||
return;
|
||||
}
|
||||
jsDebug("jswrap_wifi_connect: esp_wifi_set_config done");
|
||||
jsDebug(DBG_INFO, "jswrap_wifi_connect: esp_wifi_set_config done");
|
||||
|
||||
// Perform an esp_wifi_start
|
||||
jsDebug("jswrap_wifi_connect: esp_wifi_start %s",ssid);
|
||||
jsDebug(DBG_INFO, "jswrap_wifi_connect: esp_wifi_start %s",ssid);
|
||||
err = esp_wifi_start();
|
||||
if (err != ESP_OK) {
|
||||
jsError( "jswrap_wifi_connect: esp_wifi_start: %d(%s)", err,wifiErrorToString(err));
|
||||
@ -1307,7 +1301,7 @@ JsVar *jswrap_wifi_getAPDetails(JsVar *jsCallback) {
|
||||
} // End of jswrap_wifi_getAPDetails
|
||||
|
||||
void jswrap_wifi_save(JsVar *what) {
|
||||
jsDebug("Wifi.save");
|
||||
jsDebug(DBG_INFO, "Wifi.save");
|
||||
JsVar *o = jsvNewObject();
|
||||
if (!o) return;
|
||||
|
||||
@ -1315,7 +1309,7 @@ void jswrap_wifi_save(JsVar *what) {
|
||||
JsVar *name = jsvNewFromString(WIFI_CONFIG_STORAGE_NAME);
|
||||
jswrap_storage_erase(name);
|
||||
jsvUnLock(name);
|
||||
jsDebug("Wifi.save(clear)");
|
||||
jsDebug(DBG_INFO, "Wifi.save(clear)");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1353,16 +1347,16 @@ void jswrap_wifi_save(JsVar *what) {
|
||||
jswrap_storage_write(name,o,0,0);
|
||||
jsvUnLock2(name,o);
|
||||
|
||||
jsDebug("Wifi.save: write completed");
|
||||
jsDebug(DBG_INFO, "Wifi.save: write completed");
|
||||
}
|
||||
|
||||
void jswrap_wifi_restore(void) {
|
||||
jsDebug("jswrap_wifi_restore");
|
||||
jsDebug(DBG_INFO, "jswrap_wifi_restore");
|
||||
|
||||
JsVar *name = jsvNewFromString(WIFI_CONFIG_STORAGE_NAME);
|
||||
JsVar *o = jswrap_storage_readJSON(name, true);
|
||||
if (!o) { // no data
|
||||
jsDebug("jswrap_wifi_restore: No data - Starting default AP");
|
||||
jsDebug(DBG_INFO, "jswrap_wifi_restore: No data - Starting default AP");
|
||||
esp_wifi_start();
|
||||
jsvUnLock2(name,o);
|
||||
return;
|
||||
@ -1458,7 +1452,7 @@ void jswrap_wifi_restore(void) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
jsDebug( "Wifi: Both STA AND APSTA are off");
|
||||
jsDebug(DBG_INFO, "Wifi: Both STA AND APSTA are off");
|
||||
}
|
||||
} // End of jswrap_wifi_restore
|
||||
|
||||
@ -1533,7 +1527,7 @@ void jswrap_wifi_setHostname(
|
||||
) {
|
||||
char hostname[256];
|
||||
jsvGetString(jsHostname, hostname, sizeof(hostname));
|
||||
jsDebug("Wifi.setHostname: %s\n", hostname);
|
||||
jsDebug(DBG_INFO, "Wifi.setHostname: %s\n", hostname);
|
||||
tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA,hostname);
|
||||
|
||||
// now update mDNS
|
||||
|
||||
@ -202,6 +202,9 @@ JsVar *jswrap_ethernet_getIP(JsVar *wlanObj, JsVar *callback) {
|
||||
networkPutAddressAsString(data, "ip", &gWIZNETINFO.ip[0], 4, 10, '.');
|
||||
networkPutAddressAsString(data, "subnet", &gWIZNETINFO.sn[0], 4, 10, '.');
|
||||
networkPutAddressAsString(data, "gateway", &gWIZNETINFO.gw[0], 4, 10, '.');
|
||||
if ( !gWIZNETINFO.gw[0] ) {
|
||||
gWIZNETINFO.dns[0] = gWIZNETINFO.dns[1] = gWIZNETINFO.dns[2] = gWIZNETINFO.dns[3] = 0;
|
||||
}
|
||||
networkPutAddressAsString(data, "dns", &gWIZNETINFO.dns[0], 4, 10, '.');
|
||||
networkPutAddressAsString(data, "mac", &gWIZNETINFO.mac[0], 6, 16, ':');
|
||||
|
||||
|
||||
@ -148,3 +148,4 @@ LDFLAGS+= -L$(ESP_APP_TEMPLATE_PATH)/build/components/bt/bluedroid/api \
|
||||
-L$(ESP_APP_TEMPLATE_PATH)/build/components/bt/bluedroid/bta
|
||||
endif
|
||||
|
||||
FLASH_BAUD ?= 921600 # The flash baud rate
|
||||
|
||||
@ -31,7 +31,7 @@ flash: $(PROJ_NAME).bin
|
||||
python $(ESP_IDF_PATH)/components/esptool_py/esptool/esptool.py \
|
||||
--chip esp32 \
|
||||
--port ${COMPORT} \
|
||||
--baud 921600 \
|
||||
--baud $(FLASH_BAUD) \
|
||||
write_flash \
|
||||
-z \
|
||||
--flash_mode "dio" \
|
||||
@ -43,6 +43,6 @@ flash: $(PROJ_NAME).bin
|
||||
erase_flash:
|
||||
python $(ESP_IDF_PATH)/components/esptool_py/esptool/esptool.py \
|
||||
--chip esp32 \
|
||||
--port ${COMPORT}\
|
||||
--baud 921600 \
|
||||
--port ${COMPORT} \
|
||||
--baud $(FLASH_BAUD) \
|
||||
erase_flash
|
||||
|
||||
@ -441,8 +441,8 @@ var vector_font_c = `/*
|
||||
const uint8_t vfFirstChar = ${firstChar};
|
||||
const uint8_t vfLastChar = ${lastChar};
|
||||
#define VF_CHAR_WIDTH ${charWidth}
|
||||
#define VF_SCALE 12
|
||||
#define VF_OFFSET_Y (-3)
|
||||
#define VF_SCALE 16
|
||||
#define VF_OFFSET_Y (-2)
|
||||
#define VF_CHAR_SPACING 1
|
||||
static const uint8_t vfPolyVerts[] IN_FLASH_MEMORY = {
|
||||
${uniquePolys.map(p => p.join(",")).join(",\n ")}
|
||||
|
||||
@ -421,6 +421,8 @@ def get_ifdef_description(d):
|
||||
if d=="USE_FLASHFS": return "devices with filesystem in Flash support enabled (ESP32 only)"
|
||||
if d=="USE_TERMINAL": return "devices with VT100 terminal emulation enabled (Pixl.js only)"
|
||||
if d=="USE_TELNET": return "devices with Telnet enabled (Linux, ESP8266 and ESP32)"
|
||||
if d=="USE_WIZNET": return "builds with support for WIZnet Ethernet modules built in"
|
||||
if d=="USE_NFC": return "NFC (Puck.js, Pixl.js, MDBT42Q)"
|
||||
print("WARNING: Unknown ifdef '"+d+"' in common.get_ifdef_description")
|
||||
return d
|
||||
|
||||
|
||||
215
src/jsflash.c
215
src/jsflash.c
@ -21,12 +21,6 @@
|
||||
#define SAVED_CODE_BOOTCODE ".bootcde" // bootcode that doesn't run after reset
|
||||
#define SAVED_CODE_VARIMAGE ".varimg" // Image of all JsVars written to flash
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(...) jsiConsolePrintf("[Flash] "__VA_ARGS__)
|
||||
#else
|
||||
#define DBG(...)
|
||||
#endif
|
||||
|
||||
#define JSF_START_ADDRESS FLASH_SAVED_CODE_START
|
||||
#define JSF_END_ADDRESS (FLASH_SAVED_CODE_START+FLASH_SAVED_CODE_LENGTH)
|
||||
|
||||
@ -146,13 +140,13 @@ static bool jsfEraseFrom(uint32_t startAddr) {
|
||||
|
||||
/// Erase the entire contents of the memory store
|
||||
bool jsfEraseAll() {
|
||||
DBG("EraseAll\n");
|
||||
jsDebug(DBG_INFO,"EraseAll\n");
|
||||
return jsfEraseFrom(JSF_START_ADDRESS);
|
||||
}
|
||||
|
||||
/// When a file is found in memory, erase it (by setting first bytes of name to 0). addr=ptr to data, NOT header
|
||||
static void jsfEraseFileInternal(uint32_t addr, JsfFileHeader *header) {
|
||||
DBG("EraseFile 0x%08x\n", addr);
|
||||
jsDebug(DBG_INFO,"EraseFile 0x%08x\n", addr);
|
||||
|
||||
addr -= (uint32_t)sizeof(JsfFileHeader);
|
||||
addr += (uint32_t)((char*)&header->name.firstChars - (char*)header);
|
||||
@ -280,93 +274,138 @@ static uint32_t jsfGetAllocatedSpace(uint32_t addr, bool allPages, uint32_t *unc
|
||||
return allocated;
|
||||
}
|
||||
|
||||
// Copy one memory buffer to another *circular buffer*
|
||||
static void memcpy_circular(char *dst, uint32_t *dstIndex, uint32_t dstSize, char *src, size_t len) {
|
||||
while (len--) {
|
||||
dst[*dstIndex] = *(src++);
|
||||
*dstIndex = (*dstIndex+1) % dstSize;
|
||||
}
|
||||
}
|
||||
|
||||
static void jsfCompactWriteBuffer(uint32_t *writeAddress, uint32_t readAddress, char *swapBuffer, uint32_t swapBufferSize, uint32_t *swapBufferUsed, uint32_t *swapBufferTail) {
|
||||
uint32_t nextFlashPage = jsfGetAddressOfNextPage(*writeAddress);
|
||||
// write any data between swapBufferTail and the end of the buffer
|
||||
while (*swapBufferUsed) {
|
||||
uint32_t s = *swapBufferUsed;
|
||||
// don't read past end - it's circular
|
||||
if (s+*swapBufferTail > swapBufferSize)
|
||||
s = swapBufferSize - *swapBufferTail;
|
||||
// don't write into a new page
|
||||
if (s+*writeAddress > nextFlashPage)
|
||||
s = nextFlashPage-*writeAddress;
|
||||
if (readAddress < nextFlashPage) {
|
||||
jsDebug(DBG_INFO,"compact> skip write (0x%08x) as we're still reading from the page (0x%08x)\n", &writeAddress, readAddress);
|
||||
return;
|
||||
}
|
||||
jsDebug(DBG_INFO,"compact> write %d from buf[%d] => 0x%08x\n", s, *swapBufferTail, *writeAddress);
|
||||
if (!jsfIsErased(*writeAddress, s)) {
|
||||
jshFlashErasePage(*writeAddress);
|
||||
}
|
||||
assert(jsfIsErased(*writeAddress, s));
|
||||
jshFlashWrite(&swapBuffer[*swapBufferTail], *writeAddress, s);
|
||||
*writeAddress += s;
|
||||
nextFlashPage = jsfGetAddressOfNextPage(*writeAddress);
|
||||
*swapBufferTail = (*swapBufferTail+s) % swapBufferSize;
|
||||
*swapBufferUsed -= s;
|
||||
}
|
||||
}
|
||||
|
||||
/* Try and compact saved data so it'll fit in Flash again.
|
||||
* TO RUN THIS, 'ALLOCATED' MUST BE CORRECT, AND THERE MUST BE ENOUGH STACK FREE
|
||||
*/
|
||||
static bool jsfCompactInternal(uint32_t startAddress, uint32_t allocated) {
|
||||
DBG("Compacting from 0x%08x\n", startAddress);
|
||||
if (allocated>0) {
|
||||
// allocated = amount of RAM needed to compact all pages
|
||||
// All our allocated data will fit in RAM - awesome!
|
||||
// Allocate RAM
|
||||
char *swapBuffer = alloca(allocated);
|
||||
char *swapBufferPtr = swapBuffer;
|
||||
// Copy all data to swap
|
||||
DBG("Compacting - copy data to swap\n");
|
||||
JsfFileHeader header;
|
||||
memset(&header,0,sizeof(JsfFileHeader));
|
||||
uint32_t addr = startAddress;
|
||||
if (jsfGetFileHeader(addr, &header, true)) do {
|
||||
if (header.name.firstChars != 0) { // if not replaced
|
||||
memcpy(swapBufferPtr, &header, sizeof(JsfFileHeader));
|
||||
swapBufferPtr += sizeof(JsfFileHeader);
|
||||
uint32_t alignedSize = jsfAlignAddress(jsfGetFileSize(&header));
|
||||
jshFlashRead(swapBufferPtr, addr+(uint32_t)sizeof(JsfFileHeader), alignedSize);
|
||||
memset(&swapBufferPtr[jsfGetFileSize(&header)], 0xFF, alignedSize-jsfGetFileSize(&header));
|
||||
swapBufferPtr += alignedSize;
|
||||
}
|
||||
} while (jsfGetNextFileHeader(&addr, &header, GNFH_GET_ALL));
|
||||
// Erase everything
|
||||
DBG("Compacting - erasing pages\n");
|
||||
jsfEraseFrom(startAddress);
|
||||
// Copy data back
|
||||
DBG("Compacting - copy data from swap\n");
|
||||
char *swapBufferEnd = swapBufferPtr;
|
||||
swapBufferPtr = swapBuffer;
|
||||
while (swapBufferPtr < swapBufferEnd) {
|
||||
memcpy(&header, swapBufferPtr, sizeof(JsfFileHeader));
|
||||
swapBufferPtr += sizeof(JsfFileHeader);
|
||||
JsfFileHeader newHeader;
|
||||
uint32_t newFile = jsfCreateFile(header.name, jsfGetFileSize(&header), jsfGetFileFlags(&header), &newHeader);
|
||||
static bool jsfCompactInternal(uint32_t startAddress, char *swapBuffer, uint32_t swapBufferSize) {
|
||||
uint32_t writeAddress = startAddress;
|
||||
jsDebug(DBG_INFO,"Compacting from 0x%08x (%d byte buffer)\n", startAddress, swapBufferSize);
|
||||
uint32_t swapBufferHead = 0;
|
||||
uint32_t swapBufferTail = 0;
|
||||
uint32_t swapBufferUsed = 0;
|
||||
JsfFileHeader header;
|
||||
memset(&header,0,sizeof(JsfFileHeader));
|
||||
uint32_t addr = startAddress;
|
||||
if (jsfGetFileHeader(addr, &header, true)) do {
|
||||
if (header.name.firstChars != 0) { // if not replaced
|
||||
jsDebug(DBG_INFO,"compact> copying file at 0x%08x\n", addr);
|
||||
// Copy the file into the circular buffer, one bit at a time.
|
||||
// Write the header
|
||||
memcpy_circular(swapBuffer, &swapBufferHead, swapBufferSize, (char*)&header, sizeof(JsfFileHeader));
|
||||
swapBufferUsed += (uint32_t)sizeof(JsfFileHeader);
|
||||
// Write the contents
|
||||
uint32_t alignedSize = jsfAlignAddress(jsfGetFileSize(&header));
|
||||
if (newFile) jshFlashWrite(swapBufferPtr, newFile, alignedSize);
|
||||
swapBufferPtr += alignedSize;
|
||||
uint32_t alignedPtr = addr+(uint32_t)sizeof(JsfFileHeader);
|
||||
jsfCompactWriteBuffer(&writeAddress, alignedPtr, swapBuffer, swapBufferSize, &swapBufferUsed, &swapBufferTail);
|
||||
while (alignedSize) {
|
||||
// How much space do we have available in our swapBuffer
|
||||
uint32_t s = swapBufferSize-swapBufferUsed;
|
||||
if (s > swapBufferSize-swapBufferHead)
|
||||
s = swapBufferSize-swapBufferHead;
|
||||
if ((swapBufferTail>swapBufferHead) && (s > (swapBufferTail-swapBufferHead)))
|
||||
s = swapBufferTail-swapBufferHead;
|
||||
if (s==0) {
|
||||
jsDebug(DBG_INFO,"compact> error - no space left!\n");
|
||||
return false;
|
||||
}
|
||||
if (s>alignedSize) s=alignedSize;
|
||||
jsDebug(DBG_INFO,"compact> read %d from 0x%08x => buf[%d]\n", s, alignedPtr, swapBufferHead);
|
||||
jshFlashRead(&swapBuffer[swapBufferHead], alignedPtr, s);
|
||||
alignedSize -= s;
|
||||
alignedPtr += s;
|
||||
swapBufferUsed += s;
|
||||
swapBufferHead = (swapBufferHead+s) % swapBufferSize;
|
||||
// Is the buffer big enough to write?
|
||||
jsfCompactWriteBuffer(&writeAddress, alignedPtr, swapBuffer, swapBufferSize, &swapBufferUsed, &swapBufferTail);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DBG("Compacting - no data, just erasing page\n");
|
||||
jsfEraseFrom(startAddress);
|
||||
}
|
||||
DBG("Compaction Complete\n");
|
||||
} while (jsfGetNextFileHeader(&addr, &header, GNFH_GET_ALL));
|
||||
jsDebug(DBG_INFO,"compact> finished reading...\n");
|
||||
// try and write the remaining
|
||||
jsfCompactWriteBuffer(&writeAddress, JSF_END_ADDRESS, swapBuffer, swapBufferSize, &swapBufferUsed, &swapBufferTail);
|
||||
// Finished - erase remaining
|
||||
jsDebug(DBG_INFO,"compact> almost there - erase remaining pages\n");
|
||||
writeAddress = jsfGetAddressOfNextPage(writeAddress-1);
|
||||
jsfEraseFrom(writeAddress);
|
||||
jsDebug(DBG_INFO,"Compaction Complete\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Try and compact saved data so it'll fit in Flash again
|
||||
bool jsfCompact() {
|
||||
DBG("Compacting\n");
|
||||
uint32_t addr = JSF_START_ADDRESS;
|
||||
jsDebug(DBG_INFO,"Compacting\n");
|
||||
uint32_t pageSize = jsfGetAddressOfNextPage(JSF_START_ADDRESS) - JSF_START_ADDRESS;
|
||||
uint32_t maxRequired = pageSize + (uint32_t)sizeof(JsfFileHeader);
|
||||
// TODO: We could skip forward pages if we think they are already fully compacted?
|
||||
|
||||
/* Try and compact the whole area first, but if that
|
||||
* fails, keep skipping forward pages until we have
|
||||
* enough RAM free that it's ok. */
|
||||
while (addr) {
|
||||
uint32_t uncompacted = 0;
|
||||
uint32_t allocated = jsfGetAllocatedSpace(addr, true, &uncompacted);
|
||||
if (!uncompacted) {
|
||||
DBG("Already fully compacted\n");
|
||||
return true;
|
||||
}
|
||||
if (allocated+1024 < jsuGetFreeStack()) {
|
||||
DBG("Compacting - all data fits in RAM for 0x%08x (%d bytes)\n", addr, allocated);
|
||||
return jsfCompactInternal(addr, allocated);
|
||||
} else {
|
||||
DBG("Compacting - Not enough memory for 0x%08x (%d bytes)\n", addr, allocated);
|
||||
}
|
||||
// move to the next available page and try from there
|
||||
addr = jsfGetAddressOfNextStartPage(addr);
|
||||
uint32_t uncompacted = 0;
|
||||
uint32_t allocated = jsfGetAllocatedSpace(JSF_START_ADDRESS, true, &uncompacted);
|
||||
if (!uncompacted) {
|
||||
jsDebug(DBG_INFO,"Already fully compacted\n");
|
||||
return true;
|
||||
}
|
||||
DBG("Compacting - not enough memory to compact anything\n");
|
||||
/* TODO: we should try and compact pages at the start as well.
|
||||
* Currently we just skip pages from the front until we have
|
||||
* enough RAM. By doing both we could work either side of a
|
||||
* massive saved code area. */
|
||||
|
||||
uint32_t swapBufferSize = allocated;
|
||||
if (swapBufferSize > maxRequired) swapBufferSize=maxRequired;
|
||||
// See if we have enough memory...
|
||||
if (swapBufferSize+256 < jsuGetFreeStack()) {
|
||||
jsDebug(DBG_INFO,"Enough stack for %d byte buffer\n", swapBufferSize);
|
||||
char *swapBuffer = alloca(swapBufferSize);
|
||||
return jsfCompactInternal(JSF_START_ADDRESS, swapBuffer, swapBufferSize);
|
||||
} else {
|
||||
jsDebug(DBG_INFO,"Not enough stack for (%d bytes)\n", swapBufferSize);
|
||||
JsVar *buf = jsvNewFlatStringOfLength(swapBufferSize);
|
||||
if (buf) {
|
||||
jsDebug(DBG_INFO,"Allocated data in JsVars\n");
|
||||
char *swapBuffer = jsvGetFlatStringPointer(buf);
|
||||
bool r = jsfCompactInternal(JSF_START_ADDRESS, swapBuffer, swapBufferSize);
|
||||
jsvUnLock(buf);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
jsDebug(DBG_INFO,"Not enough memory to compact anything\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Create a new 'file' in the memory store - DOES NOT remove existing files with same name. Return the address of data start, or 0 on error
|
||||
static uint32_t jsfCreateFile(JsfFileName name, uint32_t size, JsfFileFlags flags, JsfFileHeader *returnedHeader) {
|
||||
DBG("CreateFile (%d bytes)\n", size);
|
||||
jsDebug(DBG_INFO,"CreateFile (%d bytes)\n", size);
|
||||
uint32_t requiredSize = jsfAlignAddress(size)+(uint32_t)sizeof(JsfFileHeader);
|
||||
bool compacted = false;
|
||||
uint32_t addr = 0;
|
||||
@ -392,12 +431,12 @@ static uint32_t jsfCreateFile(JsfFileName name, uint32_t size, JsfFileFlags flag
|
||||
if (!compacted) {
|
||||
compacted = true;
|
||||
if (!jsfCompact()) {
|
||||
DBG("CreateFile - Compact failed\n");
|
||||
jsDebug(DBG_INFO,"CreateFile - Compact failed\n");
|
||||
return 0;
|
||||
}
|
||||
addr = JSF_START_ADDRESS; // addr->startAddr = restart
|
||||
} else {
|
||||
DBG("CreateFile - Not enough space\n");
|
||||
jsDebug(DBG_INFO,"CreateFile - Not enough space\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -412,16 +451,16 @@ static uint32_t jsfCreateFile(JsfFileName name, uint32_t size, JsfFileFlags flag
|
||||
(spaceAvailable > (size + nextPage - addr)) && // there is space
|
||||
(requiredSize < 512) && // it's not too big. We should always try and put big files as near the start as possible. See note in jsfCompact
|
||||
!jsfGetFileHeader(nextPage, &header, false)) { // the next page is free
|
||||
DBG("CreateFile straddles page boundary, pushed to next page (0x%08x -> 0x%08x)\n", addr, nextPage);
|
||||
jsDebug(DBG_INFO,"CreateFile straddles page boundary, pushed to next page (0x%08x -> 0x%08x)\n", addr, nextPage);
|
||||
addr = nextPage;
|
||||
}
|
||||
// write out the header
|
||||
DBG("CreateFile new 0x%08x\n", addr+(uint32_t)sizeof(JsfFileHeader));
|
||||
jsDebug(DBG_INFO,"CreateFile new 0x%08x\n", addr+(uint32_t)sizeof(JsfFileHeader));
|
||||
header.size = size | (flags<<24);
|
||||
header.name = name;
|
||||
DBG("CreateFile write header\n");
|
||||
jsDebug(DBG_INFO,"CreateFile write header\n");
|
||||
jshFlashWrite(&header,addr,(uint32_t)sizeof(JsfFileHeader));
|
||||
DBG("CreateFile written header\n");
|
||||
jsDebug(DBG_INFO,"CreateFile written header\n");
|
||||
if (returnedHeader) *returnedHeader = header;
|
||||
return addr+(uint32_t)sizeof(JsfFileHeader);
|
||||
}
|
||||
@ -573,14 +612,14 @@ bool jsfWriteFile(JsfFileName name, JsVar *data, JsfFileFlags flags, JsVarInt of
|
||||
flags==jsfGetFileFlags(&header) &&
|
||||
dLen==size && // setting all in one go
|
||||
jsfIsEqual(addr, (unsigned char*)dPtr, (uint32_t)dLen)) {
|
||||
DBG("jsfWriteFile files Equal\n");
|
||||
jsDebug(DBG_INFO,"jsfWriteFile files Equal\n");
|
||||
return true;
|
||||
}
|
||||
if (addr) { // file exists, remove it!
|
||||
DBG("jsfWriteFile remove existing file\n");
|
||||
jsDebug(DBG_INFO,"jsfWriteFile remove existing file\n");
|
||||
jsfEraseFileInternal(addr, &header);
|
||||
}
|
||||
DBG("jsfWriteFile create file\n");
|
||||
jsDebug(DBG_INFO,"jsfWriteFile create file\n");
|
||||
addr = jsfCreateFile(name, (uint32_t)size, flags, &header);
|
||||
}
|
||||
if (!addr) {
|
||||
@ -596,9 +635,9 @@ bool jsfWriteFile(JsfFileName name, JsVar *data, JsfFileFlags flags, JsVarInt of
|
||||
jsExceptionHere(JSET_ERROR, "File already written with different data");
|
||||
return false;
|
||||
}
|
||||
DBG("jsfWriteFile write contents\n");
|
||||
jsDebug(DBG_INFO,"jsfWriteFile write contents\n");
|
||||
jshFlashWriteAligned(dPtr, addr, (uint32_t)dLen);
|
||||
DBG("jsfWriteFile written contents\n");
|
||||
jsDebug(DBG_INFO,"jsfWriteFile written contents\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -754,7 +754,7 @@ void jslTokenAsString(int token, char *str, size_t len) {
|
||||
case LEX_UNFINISHED_COMMENT : strcpy(str, "UNFINISHED COMMENT"); return;
|
||||
case 255 : strcpy(str, "[ERASED]"); return;
|
||||
}
|
||||
if (token>=_LEX_OPERATOR_START && token<_LEX_R_LIST_END) {
|
||||
if (token>=_LEX_OPERATOR_START && token<=_LEX_R_LIST_END) {
|
||||
const char tokenNames[] =
|
||||
/* LEX_EQUAL : */ "==\0"
|
||||
/* LEX_TYPEEQUAL : */ "===\0"
|
||||
|
||||
@ -1444,9 +1444,7 @@ NO_INLINE JsVar *jspeArrowFunction(JsVar *funcVar, JsVar *a) {
|
||||
|
||||
bool expressionOnly = lex->tk!='{';
|
||||
jspeFunctionDefinitionInternal(funcVar, expressionOnly);
|
||||
if (execInfo.thisVar) {
|
||||
jsvObjectSetChild(funcVar, JSPARSE_FUNCTION_THIS_NAME, execInfo.thisVar);
|
||||
}
|
||||
jsvObjectSetChild(funcVar, JSPARSE_FUNCTION_THIS_NAME, execInfo.thisVar);
|
||||
return funcVar;
|
||||
}
|
||||
|
||||
@ -1878,8 +1876,14 @@ NO_INLINE JsVar *__jspeBinaryExpression(JsVar *a, unsigned int lastPrecedence) {
|
||||
char nameBuf[JSLEX_MAX_TOKEN_LENGTH];
|
||||
if (jsvGetString(av, nameBuf, sizeof(nameBuf)) < sizeof(nameBuf))
|
||||
varFound = jswBinarySearch(syms, bv, nameBuf);
|
||||
bool found = varFound!=0;
|
||||
jsvUnLock2(a, varFound);
|
||||
a = jsvNewFromBool(varFound!=0);
|
||||
if (!found && jsvIsArrayBuffer(bv)) {
|
||||
JsVarFloat f = jsvGetFloat(av); // if not a number this will be NaN, f==floor(f) fails
|
||||
if (f==floor(f) && f>=0 && f<jsvGetArrayBufferLength(bv))
|
||||
found = true;
|
||||
}
|
||||
a = jsvNewFromBool(found);
|
||||
} else { // not built-in, just assume we can't do it
|
||||
jsExceptionHere(JSET_ERROR, "Cannot use 'in' operator to search a %t", bv);
|
||||
jsvUnLock(a);
|
||||
|
||||
@ -400,6 +400,22 @@ typedef enum {
|
||||
|
||||
void jsAssertFail(const char *file, int line, const char *expr);
|
||||
|
||||
#define DBG_INFO 0
|
||||
#define DBG_VERBOSE 1
|
||||
|
||||
/*
|
||||
#if defined(DEBUG) || __FILE__ == DEBUG_FILE
|
||||
#define jsDebug(dbg_type, format, ...) jsiConsolePrintf("[" __FILE__ "]:" format, ## __VA_ARGS__)
|
||||
#else
|
||||
#define jsDebug(dbg_type, format, ...) do { } while(0)
|
||||
#endif
|
||||
*/
|
||||
#if (defined DEBUG ) || ( defined __FILE__ == DEBUG_FILE)
|
||||
#define jsDebug(dbg_type, format, ...) jsiConsolePrintf("[" __FILE__ "]:" format, ## __VA_ARGS__)
|
||||
#else
|
||||
#define jsDebug(dbg_type, format, ...) do { } while(0)
|
||||
#endif
|
||||
|
||||
#ifndef USE_FLASH_MEMORY
|
||||
// Normal functions thet place format string in ram
|
||||
void jsExceptionHere(JsExceptionType type, const char *fmt, ...);
|
||||
|
||||
@ -3266,23 +3266,26 @@ void jsvArrayAddUnique(JsVar *arr, JsVar *v) {
|
||||
JsVar *jsvArrayJoin(JsVar *arr, JsVar *filler) {
|
||||
JsVar *str = jsvNewFromEmptyString();
|
||||
if (!str) return 0; // out of memory
|
||||
assert(!filler || jsvIsString(filler));
|
||||
|
||||
JsvIterator it;
|
||||
jsvIteratorNew(&it, arr, JSIF_EVERY_ARRAY_ELEMENT);
|
||||
JsvStringIterator itdst;
|
||||
jsvStringIteratorNew(&itdst, str, 0);
|
||||
bool first = true;
|
||||
while (!jspIsInterrupted() && jsvIteratorHasElement(&it)) {
|
||||
JsVar *key = jsvIteratorGetKey(&it);
|
||||
if (jsvIsInt(key)) {
|
||||
// add the filler
|
||||
if (filler && !first)
|
||||
jsvAppendStringVarComplete(str, filler);
|
||||
jsvStringIteratorAppendString(&itdst, filler, 0);
|
||||
first = false;
|
||||
// add the value
|
||||
JsVar *value = jsvIteratorGetValue(&it);
|
||||
if (value && !jsvIsNull(value)) {
|
||||
JsVar *valueStr = jsvAsString(value);
|
||||
if (valueStr) { // could be out of memory
|
||||
jsvAppendStringVarComplete(str, valueStr);
|
||||
jsvStringIteratorAppendString(&itdst, valueStr, 0);
|
||||
jsvUnLock(valueStr);
|
||||
}
|
||||
}
|
||||
@ -3292,6 +3295,7 @@ JsVar *jsvArrayJoin(JsVar *arr, JsVar *filler) {
|
||||
jsvIteratorNext(&it);
|
||||
}
|
||||
jsvIteratorFree(&it);
|
||||
jsvStringIteratorFree(&itdst);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
@ -556,7 +556,7 @@ Set the prototype of the given object - this is like writing
|
||||
`object.__proto__ = prototype` but is the 'proper' ES6 way of doing it
|
||||
*/
|
||||
JsVar *jswrap_object_setPrototypeOf(JsVar *object, JsVar *proto) {
|
||||
JsVar *v = (jsvIsFunction(object)||jsvIsObject(object)) ? jspGetNamedField(object, "__proto__", true) : 0;
|
||||
JsVar *v = (jsvIsFunction(object)||jsvIsObject(object)) ? jsvFindChildFromString(object, "__proto__", true) : 0;
|
||||
if (!jsvIsName(v)) {
|
||||
jsExceptionHere(JSET_TYPEERROR, "Can't extend %t\n", v);
|
||||
} else {
|
||||
|
||||
@ -41,7 +41,10 @@ void jsble_init(){
|
||||
esp_err_t ret;
|
||||
if(ESP32_Get_NVS_Status(ESP_NETWORK_BLE)){
|
||||
ret = esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
|
||||
if(ret) {jsWarn("mem release failed:%x\n",ret); return;}
|
||||
if(ret) {
|
||||
jsExceptionHere(JSET_ERROR,"mem release failed:%x\n",ret);
|
||||
return;
|
||||
}
|
||||
|
||||
if(initController()) return;
|
||||
if(initBluedroid()) return;
|
||||
@ -51,7 +54,7 @@ void jsble_init(){
|
||||
}
|
||||
else{
|
||||
ret = esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
|
||||
jsWarn("Bluetooth is disabled per ESP32.enableBLE(false)\n");
|
||||
jsWarn("Bluetooth is disabled per ESP32.enableBLE(false)\n");
|
||||
}
|
||||
}
|
||||
/** Completely deinitialise the BLE stack */
|
||||
@ -96,7 +99,9 @@ uint32_t jsble_advertising_start(){
|
||||
void jsble_advertising_stop(){
|
||||
esp_err_t status;
|
||||
status = bluetooth_gap_startAdvertizing(false);
|
||||
if(status) jsWarn("error in stop advertising:0X%x\n",status);
|
||||
if(status){
|
||||
jsExceptionHere(JSET_ERROR,"error in stop advertising:0X%x",status);
|
||||
}
|
||||
}
|
||||
/** Is BLE connected to any device at all? */
|
||||
bool jsble_has_connection(){
|
||||
@ -130,7 +135,9 @@ bool jsble_check_error(uint32_t err_code){
|
||||
}
|
||||
/// Scanning for advertisign packets
|
||||
uint32_t jsble_set_scanning(bool enabled, bool activeScan){
|
||||
if (activeScan) jsWarn("active scan not implemented\n");
|
||||
if (activeScan) {
|
||||
jsWarn("active scan not implemented\n");
|
||||
}
|
||||
bluetooth_gap_setScan(enabled);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -154,11 +154,6 @@ void jshInit() {
|
||||
if (JSHPINSTATE_I2C != 13 || JSHPINSTATE_GPIO_IN_PULLDOWN != 6 || JSHPINSTATE_MASK != 15) {
|
||||
jsError("JshPinState #defines have changed, please update pinStateToString()");
|
||||
}
|
||||
/*
|
||||
jsWarn( "JSHPINSTATE_I2C %d\n",JSHPINSTATE_I2C );
|
||||
jsWarn( "JSHPINSTATE_GPIO_IN_PULLDOWN %d\n",JSHPINSTATE_GPIO_IN_PULLDOWN );
|
||||
jsWarn( "JSHPINSTATE_MASK %d\n",JSHPINSTATE_MASK );
|
||||
*/
|
||||
gpio_isr_register(gpio_intr_handler,NULL,0,NULL); //changed to automatic assign of interrupt
|
||||
// Initialize something for each of the possible pins.
|
||||
jshPinDefaultPullup();
|
||||
|
||||
@ -40,19 +40,19 @@ static esp_err_t checkError( char * caller, esp_err_t ret ) {
|
||||
switch(ret) {
|
||||
case ESP_OK: break;
|
||||
case ESP_ERR_INVALID_ARG: {
|
||||
jsError( "%s:, Parameter error\n", caller );
|
||||
jsExceptionHere(JSET_ERROR, "%s:, Parameter error\n", caller );
|
||||
break;
|
||||
}
|
||||
case ESP_FAIL: {
|
||||
jsError( "%s:, slave doesn't ACK the transfer.\n", caller );
|
||||
jsExceptionHere(JSET_ERROR, "%s: slave doesn't ACK the transfer", caller);
|
||||
break;
|
||||
}
|
||||
case ESP_ERR_TIMEOUT: {
|
||||
jsError( "%s:, Operation timeout because the bus is busy.\n", caller );
|
||||
jsExceptionHere(JSET_ERROR, "%s:, Operation timeout because the bus is busy", caller );
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
jsError( "%s:, unknown error code %d, \n", caller, ret );
|
||||
jsExceptionHere(JSET_ERROR, "%s:, unknown error code %d", caller, ret );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -83,7 +83,7 @@ int getI2cFromDevice( IOEventFlags device ) {
|
||||
void jshI2CSetup(IOEventFlags device, JshI2CInfo *info) {
|
||||
int i2c_master_port = getI2cFromDevice(device);
|
||||
if (i2c_master_port == -1) {
|
||||
jsError("Only I2C1 and I2C2 supported");
|
||||
jsExceptionHere(JSET_ERROR,"Only I2C1 and I2C2 supported");
|
||||
return;
|
||||
}
|
||||
if(jshIsDeviceInitialised(device)){
|
||||
@ -110,13 +110,13 @@ void jshI2CSetup(IOEventFlags device, JshI2CInfo *info) {
|
||||
conf.master.clk_speed = info->bitrate;
|
||||
esp_err_t err=i2c_param_config(i2c_master_port, &conf);
|
||||
if ( err == ESP_ERR_INVALID_ARG ) {
|
||||
jsError("jshI2CSetup: Invalid arguments");
|
||||
jsExceptionHere(JSET_ERROR,"jshI2CSetup: Invalid arguments");
|
||||
return;
|
||||
}
|
||||
err=i2c_driver_install(i2c_master_port, conf.mode, 0, 0, 0);
|
||||
if ( err == ESP_OK ) {
|
||||
jsWarn("jshI2CSetup: driver installed, sda: %d scl: %d freq: %d, \n", sda, scl, info->bitrate);
|
||||
jshSetDeviceInitialised(device, true);
|
||||
jsDebug(DBG_INFO, "jshI2CSetup: driver installed, sda: %d scl: %d freq: %d, \n", sda, scl, info->bitrate);
|
||||
jshSetDeviceInitialised(device, true);
|
||||
} else {
|
||||
checkError("jshI2CSetup",err);
|
||||
}
|
||||
@ -129,7 +129,7 @@ void jshI2CWrite(IOEventFlags device,
|
||||
bool sendStop) {
|
||||
int i2c_master_port = getI2cFromDevice(device);
|
||||
if (i2c_master_port == -1) {
|
||||
jsError("Only I2C1 and I2C2 supported");
|
||||
jsExceptionHere(JSET_ERROR,"Only I2C1 and I2C2 supported");
|
||||
return;
|
||||
}
|
||||
esp_err_t ret;
|
||||
@ -153,8 +153,8 @@ void jshI2CRead(IOEventFlags device,
|
||||
}
|
||||
int i2c_master_port = getI2cFromDevice(device);
|
||||
if (i2c_master_port == -1) {
|
||||
jsError("Only I2C1 and I2C2 supported");
|
||||
return;
|
||||
jsExceptionHere(JSET_ERROR,"Only I2C1 and I2C2 supported");
|
||||
return;
|
||||
}
|
||||
esp_err_t ret;
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
|
||||
@ -124,8 +124,8 @@ void jshSPISetup(
|
||||
.flags=flags
|
||||
};
|
||||
if(SPIChannels[channelPnt].spi){
|
||||
SPIChannelReset(channelPnt);
|
||||
jsWarn("spi was already in use, removed old assignment");
|
||||
SPIChannelReset(channelPnt);
|
||||
jsDebug(DBG_INFO, "spi was already in use, removed old assignment");
|
||||
}
|
||||
esp_err_t ret=spi_bus_initialize(SPIChannels[channelPnt].HOST, &buscfg, 1);
|
||||
assert(ret==ESP_OK);
|
||||
@ -150,25 +150,23 @@ int jshSPISend(
|
||||
// Send 8 bits of data taken from "data" over the selected spi and store the returned
|
||||
// data for subsequent retrieval.
|
||||
//spiTransferBits(_spi[which_spi], (uint32_t)data, &g_lastSPIRead, 8);
|
||||
esp_err_t ret;
|
||||
esp_err_t ret;
|
||||
spi_transaction_t t;
|
||||
memset(&t, 0, sizeof(t)); //Zero out the transaction
|
||||
t.length=8; //Command is 8 bits
|
||||
t.tx_buffer=&data; //The data is the cmd itself
|
||||
// https://esp-idf.readthedocs.io/en/latest/api/spi_master.html#type-definitions
|
||||
// should this be a switch or always read?
|
||||
t.flags=SPI_TRANS_USE_RXDATA;
|
||||
t.flags=SPI_TRANS_USE_RXDATA;
|
||||
ret=spi_device_transmit(SPIChannels[channelPnt].spi, &t); //Transmit - blocks until result - need to change this?
|
||||
assert(ret == ESP_OK);
|
||||
SPIChannels[channelPnt].g_lastSPIRead=t.rx_data[0];
|
||||
|
||||
assert(ret == ESP_OK);
|
||||
SPIChannels[channelPnt].g_lastSPIRead=t.rx_data[0];
|
||||
} else {
|
||||
SPIChannels[channelPnt].g_lastSPIRead = (uint32_t)-1;
|
||||
}
|
||||
return (int)retData;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send 16 bit data through the given SPI device.
|
||||
*/
|
||||
|
||||
@ -38,12 +38,6 @@
|
||||
#define FAKE_FLASH_BLOCKSIZE FLASH_PAGE_SIZE
|
||||
#define FAKE_FLASH_BLOCKS (FLASH_TOTAL/FLASH_PAGE_SIZE)
|
||||
|
||||
#ifdef DEBUG
|
||||
#define FAKE_FLASH_DBG(...) jsiConsolePrintf(__VA_ARGS__)
|
||||
#else
|
||||
#define FAKE_FLASH_DBG(...)
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_64BITS_ALIGNMENT
|
||||
#define FLASH_UNITARY_WRITE_SIZE 4
|
||||
#else
|
||||
@ -883,7 +877,7 @@ static FILE *jshFlashOpenFile(bool dontCreate) {
|
||||
return f;
|
||||
}
|
||||
void jshFlashErasePage(uint32_t addr) {
|
||||
FAKE_FLASH_DBG("FlashErasePage 0x%08x\n", addr);
|
||||
jsDebug(DBG_VERBOSE,"FlashErasePage 0x%08x\n", addr);
|
||||
FILE *f = jshFlashOpenFile(true);
|
||||
if (!f) return; // if no file and we're erasing, we don't have to do anything
|
||||
uint32_t startAddr, pageSize;
|
||||
@ -898,7 +892,7 @@ void jshFlashErasePage(uint32_t addr) {
|
||||
fclose(f);
|
||||
}
|
||||
void jshFlashRead(void *buf, uint32_t addr, uint32_t len) {
|
||||
FAKE_FLASH_DBG("FlashRead 0x%08x %d\n", addr,len);
|
||||
jsDebug(DBG_VERBOSE,"FlashRead 0x%08x %d\n", addr,len);
|
||||
//assert(!(addr&(FLASH_UNITARY_WRITE_SIZE-1))); // sanity checks here to mirror real hardware
|
||||
//assert(!(len&(FLASH_UNITARY_WRITE_SIZE-1))); // sanity checks here to mirror real hardware
|
||||
if (addr<FLASH_START || addr>=FLASH_START+FLASH_TOTAL) {
|
||||
@ -918,7 +912,7 @@ void jshFlashRead(void *buf, uint32_t addr, uint32_t len) {
|
||||
fclose(f);
|
||||
}
|
||||
void jshFlashWrite(void *buf, uint32_t addr, uint32_t len) {
|
||||
FAKE_FLASH_DBG("FlashWrite 0x%08x %d\n", addr,len);
|
||||
jsDebug(DBG_VERBOSE,"FlashWrite 0x%08x %d\n", addr,len);
|
||||
uint32_t i;
|
||||
#ifndef SPIFLASH_BASE // for debug
|
||||
assert(!(addr&(FLASH_UNITARY_WRITE_SIZE-1))); // sanity checks here to mirror real hardware
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
global.value = 34;
|
||||
var obj = {
|
||||
value : 42,
|
||||
a : function() {
|
||||
return x=>this.value+x;
|
||||
}
|
||||
return x => this.value+x;
|
||||
},
|
||||
b : x => this.value+x
|
||||
};
|
||||
|
||||
var r = obj.a()(8);
|
||||
result = r === 50;
|
||||
var r2 = obj.b(8);
|
||||
result = r === 50 && r2===42;
|
||||
|
||||
@ -176,38 +176,38 @@ g.setFont("Vector",32);
|
||||
g.setColor(1);
|
||||
g.drawString("X");
|
||||
SHOULD_BE(`
|
||||
######...............#####......
|
||||
.#####..............######......
|
||||
..#####.............#####.......
|
||||
..######...........#####........
|
||||
...#####..........######........
|
||||
....#####.........#####.........
|
||||
....######.......#####..........
|
||||
.....#####......######..........
|
||||
......#####.....#####...........
|
||||
......######...#####............
|
||||
.......#####..######............
|
||||
........#####.#####.............
|
||||
........##########..............
|
||||
.........#########..............
|
||||
..........#######...............
|
||||
..........######................
|
||||
..........######................
|
||||
..........#######...............
|
||||
.........#########..............
|
||||
........##########..............
|
||||
........#####.#####.............
|
||||
.......#####..######............
|
||||
......######...#####............
|
||||
......#####.....#####...........
|
||||
.....#####......######..........
|
||||
....######.......#####..........
|
||||
....#####.........#####.........
|
||||
...#####..........######........
|
||||
..######...........#####........
|
||||
..#####.............#####.......
|
||||
.#####..............######......
|
||||
######...............#####......`);
|
||||
................................
|
||||
................................
|
||||
####............####............
|
||||
.####..........####.............
|
||||
..####........####..............
|
||||
..####........####..............
|
||||
...####......####...............
|
||||
....####....####................
|
||||
....####....####................
|
||||
.....####..####.................
|
||||
......########..................
|
||||
......########..................
|
||||
.......######...................
|
||||
........####....................
|
||||
........####....................
|
||||
.......######...................
|
||||
......########..................
|
||||
......########..................
|
||||
.....####..####.................
|
||||
....####....####................
|
||||
....####....####................
|
||||
...####......####...............
|
||||
..####........####..............
|
||||
..####........####..............
|
||||
.####..........####.............
|
||||
####............####............
|
||||
................................
|
||||
................................
|
||||
................................
|
||||
................................
|
||||
................................
|
||||
................................`);
|
||||
|
||||
g.clear();
|
||||
g.setColor(1);
|
||||
|
||||
@ -1,3 +1,10 @@
|
||||
/* We actually expect fillPoly to be different to drawPoly now. In order to
|
||||
be useful for rendering more complex shapes like fonts, fillPoly needs to render
|
||||
from low X,Y *up to but not including the highest pixels*.
|
||||
|
||||
Despite seeming odd, it's actually extremely common behaviour
|
||||
*/
|
||||
|
||||
var g = Graphics.createArrayBuffer(100,64,8);
|
||||
g.dump = _=>{
|
||||
var s = "";
|
||||
@ -84,15 +91,15 @@ SHOULD_BE(`
|
||||
........###.......####................###....#############....#...........#....#############........
|
||||
........#################################....#############....#...........#....#############........
|
||||
........#################################....#############....#...........#....#############........
|
||||
........###.......####................###....###.......###....#...........#....###.......###........
|
||||
........##.........##..................##....##.........##....#...#####...#....##..#####..##........
|
||||
........##.........##..................##....##.........##....#..#######..#....##.#######.##........
|
||||
........##.........##..................##....##.........##....#..#######..#....##.#######.##........
|
||||
........##.........##..................##....##.........##....#..#######..#....##.#######.##........
|
||||
........##.........##..................##....##.........##....#..#######..#....##.#######.##........
|
||||
........##.........##..................##....##.........##....#..#######..#....##.#######.##........
|
||||
........##.........##..................##....##.........##....#...#####...#....##..#####..##........
|
||||
........###.......####................###....###.......###....#...........#....###.......###........
|
||||
........###......#####...............####....###......####....#...........#....###......####........
|
||||
........##........###.................###....##........###....#...####....#....##..####..###........
|
||||
........##........###.................###....##........###....#..######...#....##.######.###........
|
||||
........##........###.................###....##........###....#..######...#....##.######.###........
|
||||
........##........###.................###....##........###....#..######...#....##.######.###........
|
||||
........##........###.................###....##........###....#..######...#....##.######.###........
|
||||
........##........###.................###....##........###....#..######...#....##.######.###........
|
||||
........##........###.................###....##........###....#...........#....##........###........
|
||||
........#################################....#############....#...........#....#############........
|
||||
........#################################....#############....#...........#....#############........
|
||||
........#################################....#############....#...........#....#############........
|
||||
........####.....######..............####....#############....#...........#....#############........
|
||||
@ -106,15 +113,15 @@ SHOULD_BE(`
|
||||
........####.....######..............####....#############....#...........#....#############........
|
||||
........#################################....#############....#...........#....#############........
|
||||
........#################################....#############....#...........#....#############........
|
||||
........####.....######..............####....###.......###....#...........#....###.......###........
|
||||
........###.......####................###....##.........##....#...#####...#....##..#####..##........
|
||||
........##.........##..................##....##.........##....#..#######..#....##.#######.##........
|
||||
........##.........##..................##....##.........##....#..#######..#....##.#######.##........
|
||||
........##.........##..................##....##.........##....#..#######..#....##.#######.##........
|
||||
........##.........##..................##....##.........##....#..#######..#....##.#######.##........
|
||||
........##.........##..................##....##.........##....#..#######..#....##.#######.##........
|
||||
........###.......####................###....##.........##....#...#####...#....##..#####..##........
|
||||
........####.....######..............####....###.......###....#...........#....###.......###........
|
||||
........####....#######.............#####....###......####....#...........#....###......####........
|
||||
........###......#####...............####....##........###....#...####....#....##..####..###........
|
||||
........##........###.................###....##........###....#..######...#....##.######.###........
|
||||
........##........###.................###....##........###....#..######...#....##.######.###........
|
||||
........##........###.................###....##........###....#..######...#....##.######.###........
|
||||
........##........###.................###....##........###....#..######...#....##.######.###........
|
||||
........##........###.................###....##........###....#..######...#....##.######.###........
|
||||
........###......#####...............####....##........###....#...........#....##........###........
|
||||
........#################################....#############....#...........#....#############........
|
||||
........#################################....#############....#...........#....#############........
|
||||
........#################################....#############....#############....#############........
|
||||
....................................................................................................
|
||||
|
||||
@ -36,21 +36,21 @@ g.setFontVector(15);
|
||||
g.drawString("4");
|
||||
SHOULD_BE(`
|
||||
................
|
||||
.......##.......
|
||||
......###.......
|
||||
.....####.......
|
||||
....#####.......
|
||||
....#####.......
|
||||
...######.......
|
||||
..###.###.......
|
||||
..###.###.......
|
||||
.###..###.......
|
||||
.##########.....
|
||||
###########.....
|
||||
###########.....
|
||||
......###.......
|
||||
......###.......
|
||||
......###.......`);
|
||||
....###.........
|
||||
....###.........
|
||||
...####.........
|
||||
..##.##.........
|
||||
.##..##.........
|
||||
.##..##.........
|
||||
#######.........
|
||||
#######.........
|
||||
.....##.........
|
||||
.....##.........
|
||||
.....##.........
|
||||
................
|
||||
................
|
||||
................
|
||||
................`);
|
||||
|
||||
|
||||
g.clear();
|
||||
|
||||
8
tests/test_object_setprototypeof.js
Normal file
8
tests/test_object_setprototypeof.js
Normal file
@ -0,0 +1,8 @@
|
||||
// https://github.com/espruino/Espruino/issues/1875
|
||||
let base = {foo: 42};
|
||||
let child = {};
|
||||
Object.setPrototypeOf(child, base);
|
||||
print(child.__proto__ == Object.prototype);
|
||||
print(Object.prototype);
|
||||
|
||||
result = (child.__proto__ != Object.prototype) && JSON.stringify(Object.prototype)=="{}";
|
||||
Loading…
x
Reference in New Issue
Block a user