-
The original espruinio only has a total of 2240 variables
>process.memory() ={ "free": 2220, "usage": 20, "total": 2240, "history": 0, "gc": 0, "gctime": 4.05120849609, "stackEndAddress": 536910432, "flash_start": 134217728, "flash_binary_end": 237128, "flash_code_start": 134459392, "flash_length": 262144 }
whereas the pico has 5100.
While I own 5 Picos, all except one are in use currently. And the one not in use does not have the right headers (pins vs. sockets) to connect it straight forward. I either have to solder new headers or get new connecting cables. And/or rework the code so that it can live with what it offers.
I also have a ESP32 dev board somewhere, but I do not have much experience with ESP32. There might be other issues.
-
I think the problem is that I need it for development. Quote:
Because this requires preparing the EEPROM in advance, it's utility may be limited to code which does not change often.
As this is work in progress, I currently need to test it often.
To get around the issue for the end-users I think I need to break the developed modules down in the end. This will certainly break the modular in favor of something like a "max3421UsbHostHID" or "max3421UsbHostStorage" or whatever is needed. Then I can remove unused constants and/or us the constant values directly.
The user will have less options to get their hands on the USB protocol, but at least they can use the devices (otherwise they might run out of memory just for connecting the external USB device).
In my case I would also need to have some code on top which takes care of processing the data I retrieved over USB.
-
Today I have advanced the development, but I guess I'm running out of memory. At least if I want to write the library very clearly (that is with meaningful variable names and constants).
In particular the constants seem to eat a lot of memory, but if I do it without, I probably loose track pretty soon as the USB specification isn't really trivial.
It would help if there is a way that the minification could replace constants by its value. So that "C.USB_SETUP_RECIPIENT_INTERFACE" would become "1" (its value).
In the end these names would be necessary as the user would need this as well in order to customize the code for dedicated USB devices.
What I have done so far is to start initializing the device and querying some basic device properties (description). Still very basic, but some constant progress.
I think I can gain some memory, by switching from the original espruino to the pico, but that would only solve it for the moment.
-
I already connected an old keyboard to my test setup, but didn't found the time so far to go further than that. In fact - as you mentioned - some basic module for USB Host handling could be written easily. From there it should be fairly easy to get some keyboard demo working.
There are just a few questions left from my side:
Can I require another module from within a module? I have found something like that in the touchscreen example, but I'm not aware issues with this approach. The touchscreen example implicitly pre-connects the ADS7843.
Rather than this, I'd like to have something like passing an interface to the usb-host module. The code should look something like:
var USBHost = require("USBHost").connect(require("max3421").connect(SPI1, A0, ...));
in the end.
Within the module I would need a way to determin what module has been passed. If it is of type max3421 it use this internally.
This would have the advantage to write the code of USBHost as independend and reusable as possible.
Alternatively, I could write a module named USBHostMax3421, which kind of inherits from Max3421. The initialization would look like this then:
var USBHostMax3421 = require("USBHostMax3421").connect(SPI1, A0, ...));
This is probably easier in the beginning, but less flexible in the long run.
Also I'm not sure how to handle interupts and gpio querries. The original arduino code uses a loop to check periodically for 'tasks'. With Espruino this translates to watches, doesn't it? If I use them, are there known issues in regards of the use in modules?
And one last question. The original code uses delays at some point to wait that some capacitors are fully loaded. So far I have translated the code directly using some time burning hack. While the time is very little (60ms), I'd like to get rid of this. Now I wonder whether there are better alternatives?
The only alternative that comes to my mind is using callbacks like:
init(onSuccess, onFail)
but that bloats the caller code and requires some more handling on that part.
Or should I use promises? While they look very smart, I tend not to use them in my web projects, because they used to be not fully supported by some browsers.
-
A wise decision. While the MAX3421E module is mostly working, it is mostly not just more than this. This means that it doesn't do much USB handling on its own so far. And for this reason it's yet untested (as there isn't much outer code available so far).
The original author and developer of the breakout board has decided to split the code into some files for accessing the MAX3421E chip on the one hand and files for USB handling on the other side. To me, this makes sens as it allows to create independent USB access solutions. As far as I have seen they can range from simple to complex and think it doesn't make sense the add more overhead than necessary.
So in my opinion, it would make sense to have this small MAX3421E module as base and several other libraries (separated by purpose) on top of it.
For the moment, some example code would probably be satisfying. Something that could later be expanded to a module. However, I fear, that even a simple device such as a keyboard, might at least introduce quite some more basic code, as all the USB enumeration and accessing needs to be done.
It's in the range of about 2-3 days of work, but personally, I can not make it this week. So you probably want to keep it open a bit longer, maybe.
-
Luckily, the device wasn't dead an thus I was finally able to make it work now. I have created a pull request to get the basic header translation for the MAX3421 ready. It's not much useful so far, as the USB enumeration and such still has to be done from external code, but at least it is now easier to get started.
-
-
-
There's also an original repository from the board I am using. It comes in 3 versions, but v1 library looks good enough for the start: https://github.com/felis/ArduinoUSBhost/
The authors homepage also contains a good manual: https://www.circuitsathome.com/usb-host-shield-hardware-manual/
Everything else can be read in the original chip specification: https://pdfserv.maximintegrated.com/en/an/AN3785.pdf
I have already started to get into it, but it seems I can't establish the SPI connection. I'm sure that I have wired everything correctly (tried both with SPI1 and SPI2), but whatever I send, I will always get back a 255 so far.
Does this maybe ring a bell for someone? If not, I'll try to connect my oscilloscope tomorow to debug it further.
-
-
What is needed to support USB-OTG with the Espruino?
Background: I have a device with an USB-OTG interface. If connected with the computer it act as slave. I can open a (serial) console and send a short command (string).
Now, I would like this to happen from an Espruino powered device (can be any board).
I figured out that the cable decides who takes the initial host role by a 5th pin. Beyond that the role can be changed from software as well.
While I don't need the latter, I just want any working combination so that I can send out a string over usb (just like as it was connected by a console).
Would it just work to prepare a cable to set the initial host/slave role to make the Espruino be slave? And what is needed to make the Espruino be the host (if possible at all)? Do I have acces to the additional 5th ID wire (actualy it's the 4th wire, labeled USB_ID in the schematics)?
-
So far, I have used it with the latest official firmware version.
With the cutting edge build I now got:ERROR: Too big to save to flash (22197 vs 20480 bytes)
This is better as it does not crash and gives me information about how much smaller the code must be.
I can use the save on send option "Direct to Flash" then. However, the code will be interpreted slightly different in that case (as also mentioned here).
Thanks for the hint about the latest version. While it doesn't fix the problem it gave me an idea what is wrong.
-
I finally have completed the code for a project, which contains a lot of "compiled;" statements and even one 'E.compiledC' block. The latter was necessary to get another speed boost by about factor 2 in my case.
In total the program barely fits into the memory, but it runs fine on the microcontroller.
However, if I want to save() it, the microcontroller freezes.
Compacting Flash... Calculating Size...
This is probably similar to the problem mentioned here, but for the Original Espruino Board.
-
I guess I should look at the documentation more properly: It's stated clear that only the Thumb-Opcodes are supported and not the Thumb-2 opcodes (except a few, which made me think that they were supported all together).
I've now downloaded the ARMv7m manual and checking the opcodes. Eventually I can improve the assembler to support more of the Thumb-2 instructions...
-
I've been working with the assembler, but it seems some of the opcodes I have tried to use are missing. This said I'm not sure if they are all supported, but looking at the specs for the STM32F103RCT6 and following the link for the Cortex™-M3 Technical
Reference Manual it seems a bit more than what is currently implemented should work (but doesn't).For example 'subs' should work or shouldn't it?
Is there a reason for this or does any list exists about what works and what doesn't?
And for the existing code is there a unit test to check whether the code produces correct output?
-
Regarding the documentation: I have inserted a reference on the assembler page and created a pull request for my changes. I also added the compiledC to the json specification, but for some reasons GitHub was unable to create a pull request for it so far.
It would be nice if both changes can make it into the main repo as it is very useful to know about this possibilities.
-
I wasn't aware of a compileC. Now that I know about it, I still doesn't find it in the documentation. If possible, a simple section about its existince would be nice.
So far I have just tested your benchmark and it leaves me optimistic that I can speed up the processing without any additions to the Espruino firmware (like the proposed quadrature oscillator). This said, I think it would be a nice addition nonetheless as it doesn't cost too much and can be used for various purposes (at least I have used the code in some of my other projects heavily).
Anyway, when trying to implement the whole thing, I ran into the problem that I needed to call sin() [cos isn't needed as it can be derrived from sin). However, it seems it isn't available by default and I don't know how to include a math library. I can still split the entire algorithm in a way that I could use Math.sin from JavaScript, but on the other hand I'm also interested in how it would work with compileC.
Over the weekend I plan to complete the code and benchmark it against the existing code (also in term of memory usage). It could be interesting to see a real world benchmark.
-
What you describe is more or less what I am doing today. If you look at the second pattern it calls heavily Math.sin (3 times per pixel). For a low number of pixels it is probably not an issue, but for about 250 pixels (=750 calls per refresh) it makes a difference.
Also this so called quadrature oscillator can come handy for other uses as well.
-
I know the space for code is limited on the espruino, but would there be space to add a simple sine wave oscillator in the Espruino?
The motivation for this is that I use a couple of espruino boards to drive some WS2812 LED installations (mostly goodnight light installation for my kids). These use slow sines waving colors in and out (from different directions and over time), which has proven to be very good to fall into sleep.
However the pure Math.sin call is pretty expensive and often just avoidable given the fact that the distance from one sample to the next stays the same. Thus a simple (sine) oscillator would work wonders performance wise. Unfortunately, if I implement these in JS code it's both too heavy in terms of memory and processing speed.
However, since the underlying math is dead simple and the implementation very small, I'd like to ask whether it is possible to implement this in the Espruino firmware.
What I want is something like this:
osc = new Oscillator(frequency, phase, amplitude); // phase defaults to 0, amplitude to 1
After the installation, sequent calls to the following member should be enough:
osc.getSineValueAndAdvance; // or a shorter name like getValue
It should just spit out the current sine value and advance to the next sample
The implementation is easy and just rely on 4 values stored in an array. The values are actually just two complex values. Let's call them 'position' and 'angle'.
The 'position' will contain the current sine (real) and cosine (imaginary) value and 'angle' the angle advance on the unit circle.
Now for every call to the function the current (real) position value should get returned. After that the next 'position' value is obtained by code like this (a simple butterfly algorithm):
var temp = position.re * angle.im - position.re * angle.im; position.im = position.re * angle.re + position.im * angle.im; position.re = temp;
The above code works for the normed unit circle (with the radius 1). However, since floating point calculations are a bit expensive on some boards, it also works if the values are fixed point. Often, even 16 bit internal values work sufficiently. This means position and angle are int16, where the unit circle radius of 1 becomes 2^31-1. With this, the integer multiplication must still be scaled (simple bit shift) to fit.
If implemented in assembler, the code could be very tiny and thus worth the addition.
What remains missing is the implementation. This is just slightly more complicated like:
angle.re = Math.sin(phase); angle.im = Math.cos(phase); pos.re = Math.sin(frequency)*amplitude; pos.im = Math.cos(frequency)*amplitude;
In the above code the amplitude is taken into account directly. However, in case of a fixed point implementation it makes sense to stay at the maxInt precision and just multiply the value per sample converting the integer into float again.
I don't know how much work this will be or how big the footprint will be in the end, but at least for my projects it will be a big improvement. The alternative is to supply the above functions by hand, which is luckily possible with the inline assembler or nativeCalls
PS: Don't take the pseudo code above for grant, it is written without testing just out of my head. For in-depth information you can look at this site: https://dspguru.com/dsp/howtos/how-to-create-oscillators-in-software/
After some refactoring and with the "direct to flash" option, I do now have enough ram available to keep going. And if not I can still switch to the pico...