Shop OBEX P1 Docs P2 Docs Learn Events
Can it really be that slow compared with an Arduino Uno ? — Parallax Forums

Can it really be that slow compared with an Arduino Uno ?

Hi

I've got one of those 64x16 LED dot matrix displays and can get a steady display on it using an Arduino Uno R3.

I was hoping to use a Prop with one cog to display a frame buffer and another to do other things including writing into the frame buffer.

So, I converted the fundamentals of the code into Spin and found that I get a very flickery display.

Probing the shift register latch data outputs on both controllers shows a significant performance difference. I attach screenshots. Dividing the frequency by the rows (16) will show the panel refresh rates.

I also attached the Arduino and Spin code examples.

Am I missing something here ?

Thanks

Comments

  • Spin is very slow. You probably want to recode the low-level routines in PASM.
  • This sounds like a job for PASM_MAN!

    Or: C using SimpleIDE.

    Spin is interpreted and is much slower than either Pasm or C.
  • Thanks guys.

    How did I know that you were going to say that ?

    I spent half the Eighties writing assembly language for just the same reason and even back then most of it was for bit banging but it feels like we shouldn't need to do that now.

    I guess that I'll just have to get on with it. Or VHDL.

  • Give C/C++ a try. You've got lots of great options there including fcache.
  • Your shift_out method is not very efficient. Try this instead:
    PRI shift_out(dataout) | i
      dataout ><= 9                        'Reverse 9 LSBs xabcdefgh to hgfedcbax.
      repeat 8
        outa[clockPin] := 0
        outa[dataPin] := (dataout >>= 1)
        outa[clockPin] := 1
    

    -Phil
  • retromicro wrote: »

    I spent half the Eighties writing assembly language for just the same reason and even back then most of it was for bit banging but it feels like we shouldn't need to do that now.

    We don't, actually and although it continues to be ignored, PropBASIC will give you PASM speed and is easier than using SPIN or any other language for that matter.

  • If you're used to C/C++, PropGCC does. Good job, with some trade offs. CMM (compact memory model) approches the size of Spin with about 2x the speed. LMM (large memory model) is native assembly instructions fetched from hub ram, so the encoding isn't as compact as CMM, but execution approaches PASM speed. Using CMM in "optimize for speed" mode will cache small routines and loops in native PASM, so it's a good compromise between the two.

    Ultimately the speed of the Arduino is because it's executing machine code, not interpreting it like Spin.
  • I converted your Arduino code to use PropWare. The "shiftOut" routine has been swapped out for PropWare's SPI class - no need to re-invent the wheel. The "digitalOut()" routines have been replaced with the PropWare::Pin class. And the write to PORTD was replaced with a PropWare::SimplePort class. The code now looks like this:
    #include <PropWare/pin.h>
    #include <PropWare/spi.h>
    
    // 64x16 Red LED matrix
    #define COL_PIXEL     64
    #define ROW_PIXEL     16
    
    using namespace PropWare;
    
    // 4-bit port for la_74138 lb_74138 lc_74138 ld_74138
    SimplePort port(Port::P3, 4, Port::OUT);
    
    Pin latchPin(Port::P8, Pin::OUT);
    const Port::Mask clockPinMask = Port::P9;
    const Port::Mask dataPinMask  = Port::P10;
    Pin en_74138(Port::P11, Pin::OUT);
    const SPI spi(dataPinMask, Port::NULL_PIN, clockPinMask, 800000);
    
    unsigned int ROW_xPixel;
    unsigned int ROW_num;
    
    extern unsigned char bitmap1[];
    extern unsigned char bitmap2[];
    extern unsigned char bbccharset[];
    
    void display_frame(unsigned char *BMP) {
        en_74138.high(); //Turn off display
    
        for (int i = 0; i < 8; ++i)
            spi.shift_out(8, ~*(BMP + (COL_PIXEL / 8) * ROW_xPixel + i));
    
        latchPin.low();
        latchPin.high();
    
        port.write(ROW_xPixel << 3); //Write PIN 3 4 5 6 la_74138 lb_74138 lc_74138 ld_74138
    
        en_74138.low();//Turn on display
    
        if (ROW_xPixel == 15)
            ROW_xPixel = 0;
        else
            ROW_xPixel++;
    }
    
    void setup() {
        en_74138.low();
    }
    
    void loop() {
    
        int dispchar = 'B';
    
        display_frame(bitmap1);
        // display_frame(bitmap2);
    
        bitmap1[4 + 0]  = *(bbccharset + (8 * (dispchar - 32)) + 0);
        bitmap1[4 + 8]  = *(bbccharset + (8 * (dispchar - 32)) + 1);
        bitmap1[4 + 16] = *(bbccharset + (8 * (dispchar - 32)) + 2);
        bitmap1[4 + 24] = *(bbccharset + (8 * (dispchar - 32)) + 3);
        bitmap1[4 + 32] = *(bbccharset + (8 * (dispchar - 32)) + 4);
        bitmap1[4 + 40] = *(bbccharset + (8 * (dispchar - 32)) + 5);
        bitmap1[4 + 48] = *(bbccharset + (8 * (dispchar - 32)) + 6);
        bitmap1[4 + 56] = *(bbccharset + (8 * (dispchar - 32)) + 7);
    
    }
    
    int main(void) {
        setup();
        while (1)
            loop();
    }
    
    unsigned char bitmap1[] = {
        0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
        0x3c, 0x3c, 0x7c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0x66, 0x66, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x6e, 0x66, 0x66, 0x0, 0x22,
        0x0, 0x0, 0x0, 0x7e, 0x66, 0x7c, 0x0, 0x22, 0x0, 0x0, 0x0, 0x76, 0x6a, 0x66, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x66, 0x6c,
        0x66, 0x0, 0x22, 0x0, 0x0, 0x0, 0x3c, 0x36, 0x7c, 0x0, 0x22, 0x0, 0x0, 0x0, 0x00, 0x00, 0x00, 0x0, 0x22, 0x0, 0x0,
        0x0, 0x0, 0x0, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x2, 0x4, 0x8, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0,
        0x0, 0x87
    };
    
    unsigned char bitmap2[] = {
        0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0B00001000, 0x0, 0x0, 0x0,
        0x0, 0x0, 0x0, 0x0, 0B00011000, 0x0, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x0, 0B00001000, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0,
        0B00001000, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0B00001000, 0x0, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x0, 0B00001000, 0x0,
        0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0B00001000, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0B00011100, 0x0, 0x0, 0x0, 0x22, 0x0,
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x2, 0x4, 0x8, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0,
        0x0, 0x0, 0x87
    };
    
    unsigned char bbccharset[] = {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x00, 0x6c, 0x6c, 0x6c,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x7f, 0x36, 0x7f, 0x36, 0x36, 0x00, 0x0c, 0x3f, 0x68, 0x3e, 0x0b, 0x7e,
        0x18, 0x00, 0x60, 0x66, 0x0c, 0x18, 0x30, 0x66, 0x06, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x6d, 0x66, 0x3b, 0x00, 0x0c,
        0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x30, 0x18, 0x0c, 0x0c,
        0x0c, 0x18, 0x30, 0x00, 0x00, 0x18, 0x7e, 0x3c, 0x7e, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x3c, 0x66, 0x6e, 0x7e, 0x76,
        0x66, 0x3c, 0x00, 0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x3c, 0x66, 0x06, 0x0c, 0x18, 0x30, 0x7e, 0x00,
        0x3c, 0x66, 0x06, 0x1c, 0x06, 0x66, 0x3c, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0x7e, 0x0c, 0x0c, 0x00, 0x7e, 0x60, 0x7c,
        0x06, 0x06, 0x66, 0x3c, 0x00, 0x1c, 0x30, 0x60, 0x7c, 0x66, 0x66, 0x3c, 0x00, 0x7e, 0x06, 0x0c, 0x18, 0x30, 0x30,
        0x30, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x3c, 0x00, 0x3c, 0x66, 0x66, 0x3e, 0x06, 0x0c, 0x38, 0x00, 0x00,
        0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x30, 0x0c, 0x18, 0x30, 0x60,
        0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30,
        0x00, 0x3c, 0x66, 0x0c, 0x18, 0x18, 0x00, 0x18, 0x00, 0x3c, 0x66, 0x6e, 0x6a, 0x6e, 0x60, 0x3c, 0x00, 0x3c, 0x66,
        0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x7c, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x60,
        0x66, 0x3c, 0x00, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0x78, 0x00, 0x7e, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x7e, 0x00,
        0x7e, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x60, 0x00, 0x3c, 0x66, 0x60, 0x6e, 0x66, 0x66, 0x3c, 0x00, 0x66, 0x66, 0x66,
        0x7e, 0x66, 0x66, 0x66, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x3e, 0x0c, 0x0c, 0x0c, 0x0c, 0x6c,
        0x38, 0x00, 0x66, 0x6c, 0x78, 0x70, 0x78, 0x6c, 0x66, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7e, 0x00, 0x63,
        0x77, 0x7f, 0x6b, 0x6b, 0x63, 0x63, 0x00, 0x66, 0x66, 0x76, 0x7e, 0x6e, 0x66, 0x66, 0x00, 0x3c, 0x66, 0x66, 0x66,
        0x66, 0x66, 0x3c, 0x00, 0x7c, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x6a, 0x6c, 0x36,
        0x00, 0x7c, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x00, 0x3c, 0x66, 0x60, 0x3c, 0x06, 0x66, 0x3c, 0x00, 0x7e, 0x18,
        0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66,
        0x3c, 0x18, 0x00, 0x63, 0x63, 0x6b, 0x6b, 0x7f, 0x77, 0x63, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x66, 0x00,
        0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x7e, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x7e, 0x00, 0x7c, 0x60, 0x60,
        0x60, 0x60, 0x60, 0x7c, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x3e, 0x06, 0x06, 0x06, 0x06, 0x06,
        0x3e, 0x00, 0x18, 0x3c, 0x66, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1c,
        0x36, 0x30, 0x7c, 0x30, 0x30, 0x7e, 0x00, 0x00, 0x00, 0x3c, 0x06, 0x3e, 0x66, 0x3e, 0x00, 0x60, 0x60, 0x7c, 0x66,
        0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x66, 0x3c, 0x00, 0x06, 0x06, 0x3e, 0x66, 0x66, 0x66, 0x3e,
        0x00, 0x00, 0x00, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, 0x1c, 0x30, 0x30, 0x7c, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00,
        0x3e, 0x66, 0x66, 0x3e, 0x06, 0x3c, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x00, 0x18, 0x00, 0x38, 0x18, 0x18,
        0x18, 0x3c, 0x00, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x70, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0x00,
        0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x36, 0x7f, 0x6b, 0x6b, 0x63, 0x00, 0x00, 0x00, 0x7c,
        0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x7c,
        0x60, 0x60, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x3e, 0x06, 0x07, 0x00, 0x00, 0x6c, 0x76, 0x60, 0x60, 0x60, 0x00, 0x00,
        0x00, 0x3e, 0x60, 0x3c, 0x06, 0x7c, 0x00, 0x30, 0x30, 0x7c, 0x30, 0x30, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x66, 0x66,
        0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x63, 0x6b, 0x6b, 0x7f, 0x36,
        0x00, 0x00, 0x00, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x3c, 0x00, 0x00,
        0x7e, 0x0c, 0x18, 0x30, 0x7e, 0x00, 0x0c, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0c, 0x00, 0x18, 0x18, 0x18, 0x00, 0x18,
        0x18, 0x18, 0x00, 0x30, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x30, 0x00, 0x31, 0x6b, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00,
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
    };
    

    And I'm getting ~5.4 kHz on the latch line which is 0.186 ms high time and so short of a low time that I don't trust the 0.25us reported by my logic analyzer.
  • Interpreters are generally dog slow, you don't get anywhere near the performance of a compiled language such as C.

  • The code above is written with PropWare simply because that is most familiar to me, and I wanted to show one way to write this in a Propeller language other than Spin. There are plenty of other ways to accomplish the same goals, including PropBASIC as Mickster pointed out, the Simple libraries provided with SimpleIDE, Tachyon, libpropeller, libpropelleruino, etc etc.
  • Your shift_out method is not very efficient. Try this instead:
    PRI shift_out(dataout) | i
      dataout ><= 9                        'Reverse 9 LSBs xabcdefgh to hgfedcbax.
      repeat 8
        outa[clockPin] := 0
        outa[dataPin] := (dataout >>= 1)
        outa[clockPin] := 1
    

    -Phil

    Thanks. So I pasted that in and got a decent increase in performance.
    800 x 480 - 88K
  • DavidZemon wrote: »
    I converted your Arduino code to use PropWare. The "shiftOut" routine has been swapped out for PropWare's SPI class - no need to re-invent the wheel. The "digitalOut()" routines have been replaced with the PropWare::Pin class. And the write to PORTD was replaced with a PropWare::SimplePort class. The code now looks like this:

    <snip>

    And I'm getting ~5.4 kHz on the latch line which is 0.186 ms high time and so short of a low time that I don't trust the 0.25us reported by my logic analyzer.

    Whoa !

    Seriously, that really brought a smile to my face thanks.

    I just need to work out where to paste it all into a blank template and I'll report back with the visual quality and a snap from the scope.
  • JasonDorieJasonDorie Posts: 1,930
    edited 2016-02-21 19:41
    SimpleTools, installed with SimpleIDE, includes shift_out().

    http://learn.parallax.com/propeller-c-simple-protocols/spi-example
  • Bummer ! I didn't look at the code too closely. When I did, I realised that this is based on C++.

    Would I be able to run this on a single cog and call from Spin code running on another ?

    Thanks

  • retromicro wrote: »
    Bummer ! I didn't look at the code too closely. When I did, I realised that this is based on C++.

    Would I be able to run this on a single cog and call from Spin code running on another ?

    Thanks

    Possible... Yes I think so. Easy? Not really. You could convert the rest of your program to C++ with spin2cpp though :)
  • Hi guys

    Just an update. I decided to learn some Propeller assembly language and now I have a very smooth display panel. There's still tidying up to do but the trickiest part is done.

    Thanks
Sign In or Register to comment.