## Where communities thrive

• Join over 1.5M+ people
• Join over 100K+ communities
• Free without limits
##### Activity
Peter Hoddie
@phoddie

Right, you can't do that. ;)

What you are overlooking is that within mcsim there are two completely separate JavaScript virtual machines. There is one for mcsim itself, which includes Piu and a handful of other modules from the Moddable SDK. The other virtual machine is for the hosted Moddable SDK project running in the simulator. That project includes whatever modules from the Moddable SDK that your project manifest uses, such as WebSockets. There might be a way to modify mcsim to include some other modules. But, we've never tried because we didn't intend for it to be used that way.

Henrique Bacelar
@hbacelar8
I see. So, is there a way to establish a communication between these two completely separate JavaScript virtual machines? Because my plan was to use the websocket module for that, since on my hosted Moddable SDK project there is a websocket server opened. Currently, I'm sending packets (websocket client) from a complete separate project running on web environment in order to control the display on the simulator. If I could instead use the interaction with the mcsim assets...
Sorry for extending on it, but any hint would be helpful
Peter Hoddie
@phoddie
Just to be sure I understand, you don't particularly want to use WebSockets. You want to establish some communication between the simulator and the project it is running. The messages could be JSON, for example. Is that correct?
Henrique Bacelar
@hbacelar8
Exactly. I was going to use WebSocket since the project mcsim is running already has a logic where the WebSocket module is used to open a server and receive packets from a web application running at localhost. In this web application, there are buttons created with HTML/CSS/JS that, when clicked, send a packet to the WebSocket server on the project. Now, I wanted to do the same but with the buttons I mapped on a .png layout imported on mcsim. So it doesn't particularly have to be WebSocket (especially now that you confirmed me it doesn't work on mcsim). I just need a way to send some data to the project the simulator is running from the simulator (mcsim) itself.
Henrique Bacelar
@hbacelar8
Hence the need of establishing a communication.
Peter Hoddie
@phoddie

The simulator already has a communication path for you to use. Here's an easy way to see that.

Add these lines at the end of $MODDABLE/examples/helloworld/main.js: screen.onMessage = function(msg) { msg = JSON.parse(msg); screen.postMessage(JSON.stringify({led: msg.button})); } Then on the command line, do this: cd$MODDABLE/examples/helloworld
mcconfig -d -m -p simulator/moddable_two

Now you can blink the light in the simulator, as shown below.

Henrique Bacelar
@hbacelar8
Peter, thanks a lot. That worker. I was able to implement it in my project. Is that kind of information documented?
Peter Hoddie
@phoddie
Glad that works! The mcsim simulator is still considered experimental and so we haven't documented it yet. That said, it works well and we use it on nearly every client project we do, so maybe it is finally time to retire the venerable screen test (our original and still default simulator) and make the switch.
I'm curious -- mcsim is pretty obscure. How did you happen across that and decide to start working with it? It is great that you did.
Henrique Bacelar
@hbacelar8
The company I'm currently working at has a project using Moddable and mcsim for simulation, but is kind of outdated. So I'm working on another project that uses Screen Test and this aforementioned WebSocket/HTML workaround to control the screen. So basically I'm working on the latter in order to fully migrate the simulation to mcsim, having all user interactions embedded on it and establishing its communication to the main application, which works fine now.
Peter Hoddie
@phoddie
Cool, thanks.
Peter Hoddie
@phoddie
Probably worth mentioning.... that outdated project you refer to uses a different mechanism for communication between the simulator and the hosted project, one that is probably a better fit here. But, I can't discuss detail of commercial projects in public forums.
Chris
@cmidgley

Hi @phoddie - been a while (just under a year!) but I'm finally back on my Moddable project. I had a simple question about destructors in XS in C. I see that the (xsMachine) isn't passed to the destructor (the object is the first parameter; perhaps it's in another parameter?) I currently store it in my object in the constructor, and then access it in the destructor like this:

void xs_example_destructor(void *data)
{
xsMachine *the = ((test *)data)->the;
xsTrace("In destructor\n");
}

It seems to be working in my very simple tests, but I was concerned I may be accessing a pointer (to the) that could be freed / invalid at this time. Is this the correct way to access the or is there a better way (or, not allowed at all)?

Peter Hoddie
@phoddie
Welcome back!!
Correct, the is not passed to the destructor. The destructor is invoked from deep within the garbage collector, which is a time when it is not safe to call XS. It might work sometimes. But, it isn't safe. None of the destructors in the Moddable SDK call XS in C APIs for that reason.
Chris
@cmidgley
That was my concern - no problem, it was just for debugging anyway.
One more Q... any hints/thoughts on how to include an Arduino CPP library (in my case, LoRa library) in the build so I can add the XS to C stubs? I plan on rewriting it to ESP-IDF to avoid the Arduino bloat, but I was hoping to experiment / work with the interface for a bit first to refine how the new API should be designed.
Peter Hoddie
@phoddie
If you just want to trace, you can safely use modLog and friends from most places (including the destructor).
Chris
@cmidgley
Great - that will be a help.
Peter Hoddie
@phoddie
(They are primitive, but that allows them to safely used in more places.)
Chris
@cmidgley

I have the CPP file in the manifest/build, but of course I get errors on including Arduino.h. I added the CPLUS_INCLUDE_PATH to reference the Arduino includes, but then run into issues with missing defines / configuration. For example, currently it fails with:

# cc LoRa.cpp.o
cc1plus.exe: warning: command line option '-Wno-implicit-function-declaration' is valid for C/ObjC but not for C++
cc1plus.exe: warning: command line option '-std=gnu99' is valid for C/ObjC but not for C++
In file included from c:\Program Files (x86)\Arduino\hardware\tools\avr\avr\include/avr/pgmspace.h:90,
from c:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:28,
from c:\Users\chris\Documents\Personal\poolidea\modtest\arduino-LoRa\src/LoRa.h:14,
from c:\Users\chris\Documents\Personal\poolidea\modtest\arduino-LoRa\src\LoRa.cpp:4:
c:\Program Files (x86)\Arduino\hardware\tools\avr\avr\include/avr/io.h:711:6: warning: #warning "device type not defined" [-Wcpp]
#    warning "device type not defined"
^~~~~~~
In file included from c:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/USBAPI.h:25,
from c:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:234,
from c:\Users\chris\Documents\Personal\poolidea\modtest\arduino-LoRa\src/LoRa.h:14,
from c:\Users\chris\Documents\Personal\poolidea\modtest\arduino-LoRa\src\LoRa.cpp:4:
c:\Program Files (x86)\Arduino\hardware\tools\avr\avr\include/avr/eeprom.h:41:3: warning: #warning "Device does not have EEPROM available." [-Wcpp]
# warning "Device does not have EEPROM available."
^~~~~~~
In file included from c:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/USBAPI.h:27,
from c:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:234,
from c:\Users\chris\Documents\Personal\poolidea\modtest\arduino-LoRa\src/LoRa.h:14,
from c:\Users\chris\Documents\Personal\poolidea\modtest\arduino-LoRa\src\LoRa.cpp:4:
c:\Program Files (x86)\Arduino\hardware\tools\avr\avr\include/util/delay.h:92:3: warning: #warning "F_CPU not defined for <util/delay.h>" [-Wcpp]
# warning "F_CPU not defined for <util/delay.h>"
^~~~~~~
In file included from c:\Users\chris\Documents\Personal\poolidea\modtest\arduino-LoRa\src/LoRa.h:14,
from c:\Users\chris\Documents\Personal\poolidea\modtest\arduino-LoRa\src\LoRa.cpp:4:
c:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:258:10: fatal error: pins_arduino.h: No such file or directory
#include "pins_arduino.h"
^~~~~~~~~~~~~~~~
compilation terminated.

I know the pins_arduino.h is just an include path, but the missing defines are more likely indicative of a more serious setup issue and likely I'm driving off the edge of a cliff....!

Peter Hoddie
@phoddie
I'm skeptical that you are going to get Arduino code compiling under IDF. But that's your challenge. You can use the recipes feature of mcconfig to set additional build flags for certain files. It is an obscure feature, but it is also why our ESP8266 build works at all. The recipes named in the manifest are contained in \$MODDABLE/tools/mcconfig, for example this is the strings-in-flash used on Mac and Linux builds.
Chris
@cmidgley
Thanks for the hint to recipes - I'll check it out. I know it's "possible" to get Arduino / ESP-IDF to work together, but was hoping to hear it was something you/others have done w/Moddable. Given that feedback, I'll refocus on porting to ESP-IDF. Thanks, Peter!
Peter Hoddie
@phoddie
The biggest challenge, as I see it, is that Arduino code hits the hardware directly, which means you have the potential conflicts with the IDF use of the same hardware. My usual approach is to read the Arduino code and then rewrite it in JavaScript. But, that's me. And for some libraries, that isn't the right answer (I don't know anything about the LoRa stuff).
Chris
@cmidgley
The LoRa stuff isn't super complex - it's SPI with ISR routines to respond to the packet receives/completions. My understanding is that ISR requires going into C (and then send it up to JS). I've not researched SPI in Moddable JS - was assuming it was best to do that in C as well, but perhaps not?
Chris
@cmidgley
I see There is no JavaScript API to access SPI at this time so I think that answers this question!
Peter Hoddie
@phoddie
There is a JavaScript API to access SPI.
It works well. Our two recent ePaper display drivers use it.
The ePaper blog post is good reading. If you really need to respond to LoRa interrupts from the ISR, then you need to use C though. If you can tolerate some latency, JavaScript could well work.
Chris
@cmidgley
Interesting! Where is the SPI interface (and is there any doc on it)? As for JS latency vs. ISR, do you mean polling instead of an ISR, or a simple C ISR that callsback to JS to handle the completion, or...? LoRa is a very slow protocol (and transmit is limited by FCC regulations to seconds or minutes between packets!), so latency of the types we are talking about wouldn't be a big deal - except I'd need to check if the chip (SX1278) is able to continue to receive a packet while awaiting the prior packet offload to make sure I didn't experience high packet loss (it is a broadcast network, no packet acknowledgement/error handling, and given FCC rules doing a retry can delay a message by minutes)
Peter Hoddie
@phoddie
The SPI class follows Ecma-419, so the standard is the documentation. Both of the new ePaper display drivers described in the blog use SPI, gdew0154m09 and IT8951 so they are good examples. The IT8951 does both read and write over SPI. Note that the latency of handling the interrupts in JavaScript is pretty small as long as the task isn't busy. You can always run that in its own virtual machine to ensure it isn't blocking if it comes to that.
To trigger the ISR, you can uses an Ecma-419 Digital class with an onReadablle callback that is invoked when the interrupt triggers. The Digital class installs an ISR and triggers your JavaScript callback. This button code is a good example of how that works.
Chris
@cmidgley

Perfect. I have the ESP-IDF port working in Moddable now (sending/receiving LoRa packets in Moddable) but I'm going to try to port to JS next as that would be much cleaner / more maintainable.

You can always run that in its own virtual machine to ensure it isn't blocking if it comes to that.

Is this using Workers? We have a discussion earlier (more than a year ago) where you said they were experimental. How are you feeling about the reliability of Workers now?

Peter Hoddie
@phoddie
We use Workers in nearly every one of the projects we build for our clients. They are solid. But, it also sounds like you might not need that here.
Chris
@cmidgley
I'm making progress - I have SPI initializing and talking to the chip, but don't yet have coms working yet. To debug I need to run two ESP32's at the same time (each with a LoRa chip). It appears I cannot run two instances of xsbug (at least on Windows) at the same time - is that correct, or is there a trick?
Peter Hoddie
@phoddie
That sounds complicated and cool. One instance of xsbug can be used with several devices simultaneously. You can see that basic support by running one app on ESP32 and another in the simulator. I think our default scripts triggered by mcconfig kill the running instance of the seriall2xsbug bridge. So, you'll probably need to manually launch serial2xsbug twice, each with a different serial port. They will both connect to the same instance of xsbug.
Chris
@cmidgley
Yes - that is working. It shows a unique machine tab for each device. I found the baud rate using mcconfig -v - it's 460800. Back to debugging!
Peter Hoddie
@phoddie
Cool.
FWIW - if/when you get to Workers, each worker appears as a separate machine tab in xsbug too.
Chris
@cmidgley
Sweet! I am now sending and receiving LoRa packets with 100% Moddable JS code! Not doing interrupts yet (currently just polling) but that shouldn't be much work at this point. Thanks for the help!
Peter Hoddie
@phoddie
That is impressive -- both that it works at all and that you did it so quickly.
Any chance of a PR at some point??
(I'm very curious to see examples using the Ecma-419 APIs.)
Daniel Ashcraft
@dashcraft
Wow!
Chris
@cmidgley
I'm glad to share the source but I don't think it will be in PR-ready condition. Done right, it should abstract away the hardware specifics from the LoRa interface (much like how SPI works) but right now it's really bringing forward the unique needs of the SX1278 chip. Plus I didn't attempt to create a full interface of all features - I implemented only the features that my project needs. When I get it cleaned up, I'll send a link to the source and you can let me know what you want to do with it (if anything).
Peter Hoddie
@phoddie
That would be great, thanks. I can imagine implementing the whole thing is a non-trivial project. FWIW - there's a very deliberate API style in Ecma-419 for IO and peripherals. That might be interesting to apply here to abstract away those hardware specifics.
Chris
@cmidgley
I wouldn't say I fully grok the Ecma-419 style, but did spend some time there to get a basic feel (and to consume the interfaces for Digital and SPI). Since this chip lives on SPI (perhaps others don't?) I wasn't clear if that meant it should have SPI instantiated outside of the LoRa object, or have the SPI pins/mode/etc passed in the dictionary on the constructor and then have the LoRa class instantiate SPI. I assumed you would just extend that dictionary for device specific features - in this case, frequency, bandwidth, coding rate, CRC, implicit/explicit, etc? Didn't see any naming standards or rules for custom extensions to that dictionary. Similar with adding methods that are unique to the class - such as getting the signal-to-noise ratio (SNR) or live changing a parameter that was specified in the constructor dictionary. Sufficient questions / lack of understanding that I didn't attempt to directly model it. Doesn't seem too difficult to fit into the model once those style issues are resolved, but as always the devil is in the details.