Shop OBEX P1 Docs P2 Docs Learn Events
c(++) classes and Fastspin — Parallax Forums

c(++) classes and Fastspin

Hi Eric,
it's me, the old nuisance... :blush:

I wonder if anybody has tried the class feature of Fastspin, yet. There is not much documantation about it and I haven't found an example. I'm experimenting with digital filters and I think this would be a well fitting application for it. I tried
typedef class
{
  float Output (float in) ;
  void SetCoefficients (float* ca, float* cb, unsigned int order);
  void Clear ();

  unsigned int n; // number of coefficients = order+1
  float x[maxCoeff]; // input samples
  float y[maxCoeff]; // output samples
  float a[maxCoeff]; // A coefficients
  float b[maxCoeff]; // B coefficients
} iirFilter;
But then I run into several problems. First, I get an error message that the methods are private. The compiler does not understand "public:" or "private:" keywords. The docs say that members of classes are always private but that makes no sense for methods. There must be public methods otherwise the class is useless as everything is unaccessable.

Second, I don't know how to tell the compiler which function implementation should be linked to the method declaration. __fromfile ("FilterIIR.c") after the declaration doesn't work. And if I just put a definition of Output() and the other functions in the .cpp file the main crashes instantly at the first method call. The compiler doesn't seem to support C++ style namespaces so that iirFiler::Output() could be defined. I'm sure I do something wrong but as long as there's no error message I can't guess what.

Of course I could just give up and do it the standard C way by supplying an explicit "this" argument to each method (implemented as standard function). But an object oriented solution would be more elegant. And there surely was a reason you mentioned classes in the fastspin docs. You just have to tell us how it's meant to be.

My intention was to allow multiple instances of filters to be created with different (private) coefficients. (high pass and low pass, see hp and lp in TestFilter.cpp) My code is likely to be full of stupid errors but I haven't got the chance to really test it much...

Comments

  • From the C.pdf documentation file:

    The C `struct` declaration is extended slightly to allow functions (methods) to be declared. These must be declared like C++ "inline" functions, that is in the struct definition itself, but are not necessarily implemented inline.

    So the only way to declare functions is directly in the "class" (or "struct", they are almost the same) declaration, as in the functions setval() and getval() in the example:
    typedef struct counter {
      int val;
      void setval(int x) { val = x; }
      int getval() { return val; }
      int incval() { return ++val; }
    } Counter;
    

    Note that the member *variables* are private in classes, but not the methods; so if you changed "struct" to "class" in the code above, then calling "x.getval()" would still be fine, but trying to read to "x.val" would not.
  • ersmith wrote: »
    ...These must be declared like C++ "inline" functions, that is in the struct definition itself, but are not necessarily implemented inline.
    Ah thanks, that makes it clear. I misread the sentence and interpreted "not necessarily implemented inline" as "not necessarily implemented in the class definition" which is of course something different.

    Again, some error message would be helpful. If the method definition must be in the class definition then IMHO the compiler should say something like "method definition expected" or at least "{ expected" after the method declaration.

    If I make such a mistake with GCC like giving an implementation the wrong name then usually the linker complains that there is no implementation or label found for a function call. The error messages are also often hard to understand because the error is not detected until the end of the whole compile+link process but at least there is one.


  • Old proverb: ...and as soon as you do everything right it suddenly works!

    Eric, you could probably add this to the Fastspin examples so nobody has to ask the same questions over and over again.
  • Oh no, I'm desperate, again.cry.gif

    I have problems understanding the error messages of the compiler. This time it's "unknown symbol __super". It must have something to do with a call of a regular function from within a class method. I checked if that was forbidden but the compiler doesn't complain if I call printf in my method.

    As there is no list file generated if the compiler doesn't succeed I have no chance finding out what went wrong. I'm sure it's again just one of my small stupid mistakes. But I fear you have to help me out, Eric.
  • @ManAtWork : it looks like the class system in fastspin is quite seriously broken for anything other than trivial classes. So for now, you'll probably have to stick to plain C. Sorry.
  • I tried to get around it by making it "more trivial", i.e. moving the external functions inside the classs definition But then the next problem came up: I can't use member variables in inline assembler. :( Sounds quite logical, that's why I used an extra function for the inline asm code in the first place so that I have easy access to the variables transferred as arguments and inside registers.

    Unfortunatelly, this makes the classes as they are now pretty useless. There is no inheritance and vitual functions so everything is more or less static. The methods can be replaced by simple function calls. Instead of
    classvar.method (arg)
    
    we can write
    method (classvar, arg)
    
    So it's just a little inconvenience and no big problem.
  • Well, in general member variables are stored in HUB memory rather than in registers, so they can't directly be used in assembly. You can use member variables indirectly though by first loading them into local variables:
    int method(int x)
    {
        int temp = member_var;
        asm {
            add x, temp
        }
        return x;
    }
    

    To be honest, I really would try to avoid inline assembly. For things that you absolutely have to do in inline assembly, keep the inline assembly short and do as much as possible in the high level language. That's kind of the whole reason for having a high level language!
  • ersmith wrote: »
    To be honest, I really would try to avoid inline assembly. For things that you absolutely have to do in inline assembly, keep the inline assembly short and do as much as possible in the high level language. That's kind of the whole reason for having a high level language!

    I totally agree when it comes to application code. But when writing low level drivers and math libraries then using assembler provides a performance advantage and sometimes it makes things possible that can't be done otherwise. For example, to use the CORDIC unit pipelined you need to meet exact timing.

    The propeller is a great device fo "hardware hacks" and things that need realtime processing. Now we have the P2 which has enough memory for big application software. The real power is to combine the two.

    The main reason that I use Fastspin is that it allows mixing languages. I can use existing libraries written in Spin. I can add small hacks in assembler. And I can write long programs in C. Being able to combine that gives us a powerful tool.

    So for good programming style, instead of avoiding assembler completely, the I'd phrase it like this: "The use of low level and high level languages should be separated as much as possible, encapsulating the low-level details inside driver and library modules". That's the whole idea of object oriented programming. Encapsulation and "divide and conquer". And sometimes, programming in assembler is just too tempting, especially on the P2. I definitely won't quit it.

    But I know what you want to say. "Often we waste too much time trying to save time". We shouldn't dig too deep otherwise we get a stack overflow and the main task never gets completed. I'll try not to bother you as long it's not absolutely necessary.
Sign In or Register to comment.