Avatar for CWBudde1


Member since Sep 2018 • Last active Dec 2018
  • 2 conversations

Most recent activity

  • in General
    Avatar for CWBudde1

    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.

  • in General
    Avatar for CWBudde1

    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.

  • in General
    Avatar for CWBudde1

    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...

  • in General
    Avatar for CWBudde1

    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?

  • in General
    Avatar for CWBudde1

    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.

  • in General
    Avatar for CWBudde1

    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.

  • in General
    Avatar for CWBudde1

    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.

  • in General
    Avatar for CWBudde1

    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-cr­eate-oscillators-in-software/