grame-cncm / faust

Functional programming language for signal processing and sound synthesis
http://faust.grame.fr
Other
2.53k stars 319 forks source link

Feature request: Add Raspberry RP2040 support #747

Open DatanoiseTV opened 2 years ago

DatanoiseTV commented 2 years ago

I have created the PicoDSP and some DSP boards around the easily available RP2040 MCU. Here is my sample code (using Vult currently instead of Faust) https://github.com/DatanoiseTV/RP2040-DSP-FreeRTOS-Template

It would be nice to see Faust support for RP2040.

sletz commented 2 years ago

Are you ready to help? Have you read https://faustdoc.grame.fr/manual/architectures/ ?

DatanoiseTV commented 2 years ago

Yes, but I am not sure where to start best. The RP2040 doesn't have a floating point unit, so all the calculations should be done using fixed point calculations. Vult DSP has included a compile option for this which transcompiles it to use 32-bit fixed point.

sletz commented 2 years ago

Hum, Faust does not have a 32-bit fixed point code generator yet. But it should have one at the end of the FAST project

mryndzionek commented 2 years ago

I'm also interested in this and been playing with CNL. I got it to compile, but the main problem I encountered is the structure, so to speak, of the computations in the generated code. Fore example even the beginning:

    fixpoint_t fConst0 = fmin((fixpoint_t)192000.0, fmax((fixpoint_t)1.0, (fixpoint_t)(dsp->fSampleRate)));
    fixpoint_t fConst1 = tan((fixpoint_t)25132.7422 / fConst0);
    fixpoint_t fConst2 = (fixpoint_t)1.0 / fConst1;

blows the range of even 128bit fixed point variables... Thetan and divisions are to blame. With 32bit fixed point numbers, like in Vult, it will only get worse. Any ideas how to fix this?

sletz commented 2 years ago

Interesting use of CNL. Is you project visible somewhere?

mryndzionek commented 2 years ago

Interesting use of CNL. Is you project visible somewhere?

No, not yet. Too experimental for now :) Also, CNL is not really suited for low-end embedded platforms (uses advanced features of C++, requires C++20, g++-10, etc..)

mryndzionek commented 2 years ago

Actually one more update on this topic. The code for sin oscillators behaves fairly okay with fixed point. The noise generator has problems. no.noise generates code like this:

        int i0;
        for (i0 = 0; i0 < count; i0 += 1) {
            dsp->iRec0[0] = (1103515245 * dsp->iRec0[1]) + 12345;
            output0[i0] = fix_to_float(fix_mul(float_to_fix(4.65661287e-10), int_to_fix(dsp->iRec0[0])));
            dsp->iRec0[1] = dsp->iRec0[0];
        }

Multiplication by 4.65661287e-10 is the problem. Anyone knows how to fix this?

sletz commented 2 years ago

Are fix_to_float, fix_mul kind of functions manually coded? (they are not yet generated but the code generator AFAICS..)

mryndzionek commented 2 years ago

Are fix_to_float, fix_mul kind of functions manually coded? (they are not yet generated but the code generator AFAICS..)

Yes. I'm aiming at C generator, so I modified it to use explicit functions instead of binary operators (C doesn't have operator overloading).

sletz commented 2 years ago

Signals in the Faust compiler have an associated interval (like a [min, max] range) with an associated symbolic computation done at each step (even is still imperfect, particularly in the presence of recursive signals). The proper way will then be to add an additional kind keep the range in this fixed-point domain constraint in the interval calculus, so that to finally generate correct code. This is not a trivial task... (and actually part of the FAST project).

How does VULT deal with fixed-point compilation?

mryndzionek commented 2 years ago

I know VULT even less than Faust :) . I think that VULT is much simpler and doesn't have so many pre-defined blocks. I've made quick experiment. In Vult there is a simple noise example:

fun pinker(x:real){
   mem w1;
   val b0 = 0.02771298631913731;
   val b1 = 0.02771298631913731;
   val a1 = -0.9445740273617255;
   val w0 = x - a1*w1;
   val y0 = b0*w0 + b1*w1;
   w1 = w0;
   return y0;
}

and this translates to:

fix16_t Ex_pinker(Ex__ctx_type_0 &_ctx, fix16_t x){
   fix16_t b0;
   b0 = 0x718 /* 0.027713 */;
   fix16_t b1;
   b1 = 0x718 /* 0.027713 */;
   fix16_t a1;
   a1 = -0xf1cf /* -0.944574 */;
   fix16_t w0;
   w0 = (x + (- fix_mul(_ctx.w1,a1)));
   fix16_t y0;
   y0 = (fix_mul(_ctx.w1,b1) + fix_mul(b0,w0));
   _ctx.w1 = w0;
   return y0;
}
mryndzionek commented 2 years ago

The proper way will then be to add an additional kind keep the range in this fixed-point domain constraint in the interval calculus, so that to finally generate correct code.

I don't think there is a way around re-implementing some (all?) of the blocks/functions into more fixed-friendly versions. Just limiting the range will still introduce artifacts and problems with more complex topologies.

sletz commented 2 years ago

Until we improve the compiler interval calculus, I don't think we can move on in the general case.

I can possibly improve the C backend so that -fx would generatefix_to_float, fix_mul kind of functions, so that as least the generated code does not have to be manually editing. Would this help?

But you'll still have range issues in a lot of DSP examples.

mryndzionek commented 2 years ago

I can possibly improve the C backend so that -fx would generatefix_to_float, fix_mul kind of functionq, so that as leaqt the generated code does not have to be manually editing. Would this help?

Yes, I think this would be better. Will work for C and C++. Also explicit casting functions would be needed (float_to_fix, fix_to_float, int_to_fix, etc).

mryndzionek commented 1 year ago

Hum, Faust does not have a 32-bit fixed point code generator yet. But it should have one at the end of the FAST project

I see that Syfala is now available. It seems to have fixed point for VHDL. Any updates on fixed point support in Faust? Maybe it would be possible to convert VHDL form Syfala to C?

crystalthoughts commented 7 months ago

Hello - is there any new status on this? is -fx enough now?