Shop OBEX P1 Docs P2 Docs Learn Events
If there is a will there is a way :) — Parallax Forums

If there is a will there is a way :)

KyeKye Posts: 2,200
edited 2011-12-27 09:19 in Propeller 1
I was just working on some high speed 8MHz byte wide data transfer code using the prop chip and I ran into a wall for how to grab and mask data quickly enough. Just... how can you grab multiple copies of INA very quickly while aligned to a clock and then store those copies of INA in an array? All hope was almost lost. But then MOVI, MOVD, and MOVS saved the day. Using those three instructions I can pack data into a long from the INA register without having to preform all the shifting and masking operations.

Simply beautiful!

Good thing I used the prop chip for the CMUcam4!

Comments

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-12-26 15:27
    How did you manage to pack four eight-bit bytes using those ops without shifting? ('Just kidding; I know that's not possible. But seeing your code would be cool.)

    -Phil
  • KyeKye Posts: 2,200
    edited 2011-12-26 16:58
    Okay, so here's what's happening.

    8 MHZ pixel clock coming into the prop chip. The prop chip is at 96 MHz. There is an 8-bit data bus from a camera attached to P0-P7. There is also a HREF and VSYNC line attached to the prop chip.

    Each pixel from the camera comes in two sequential bytes. In RGB565 mode the camera will send [r r r r r g g g] and then [g g g b b b b b] where the rgb letters represent RGB565 data from the camera. The camera will send 640 pixels. This means 1280 clock pulses will come each delivering 8 bits of data. The HREF line will only be high during these 1280 pixel clocks at 8MHZ and then will go low again until the next line of video data is sent.

    Since the prop chip is not fast enough to handle 640x480 RGB565 data I down sample the data to 160x120 RGB565.

    Here is the code:
                            mov     LNRowCounter,           #_CAMERA_V_WIN               ' Setup for the next frame.
                            waitpeq LNVSYNCMask,            LNVSYNCMask                  '
                                                   
    LNGrabberLineLoop       mov     LNColumnCounter,        #(_CAMERA_H_WIN / 2)         ' Setup for the pixel storage loop.
                            movd    LNStorePixelModify,     #(LNPixelStorage - 1)        '
    
    
    
    LNStorePixelLoop        waitpeq LNHREFMaskAndPCLKMask,  LNHREFMaskAndPCLKMask        ' Grab a pixel.
                            mov     LNFirstPartBuffer,      ina                          '
                            waitpeq LNHREFMaskAndPCLKMask,  LNHREFMaskAndPCLKMask        '
                            mov     LNSecondPartBuffer,     ina                          '
                                
                            waitpeq LNHREFMaskAndPCLKMask,  LNHREFMaskAndPCLKMask        ' Mask that pixel.
                            and     LNFirstPartBuffer,      #$FF                         '
                            waitpeq LNHREFMaskAndPCLKMask,  LNHREFMaskAndPCLKMask        ' 
                            and     LNSecondPartBuffer,     #$FF                         ' 
                                                           
                            waitpeq LNHREFMaskAndPCLKMask,  LNHREFMaskAndPCLKMask        ' Shift that pixel.
                            shl     LNFirstPartBuffer,      #16                          '
                            waitpeq LNHREFMaskAndPCLKMask,  LNHREFMaskAndPCLKMask        '
                            shl     LNSecondPartBuffer,     #8                           '
                            waitpeq LNHREFMaskAndPCLKMask,  LNHREFMaskAndPCLKMask        ' Combine that pixel.
                            or      LNFirstPartBuffer,      LNSecondPartBuffer           ' 
                            waitpeq LNHREFMaskAndPCLKMask,  LNHREFMaskAndPCLKMask        '
                            add     LNStorePixelModify,     LNDestinationIncrement       ' 
                            
                            waitpeq LNHREFMaskAndPCLKMask,  LNHREFMaskAndPCLKMask        ' Grab another pixel.
                            mov     LNThirdPartBuffer,      ina                          '
                            waitpeq LNHREFMaskAndPCLKMask,  LNHREFMaskAndPCLKMask        '
                            mov     LNFourthPartBuffer,     ina                          '
                            
                            waitpeq LNHREFMaskAndPCLKMask,  LNHREFMaskAndPCLKMask        ' Shift and mask another pixel.
                            and     LNThirdPartBuffer,      #$FF                         '
                            waitpeq LNHREFMaskAndPCLKMask,  LNHREFMaskAndPCLKMask        '
                            shl     LNFourthPartBuffer,     #24                          '
                            waitpeq LNHREFMaskAndPCLKMask,  LNHREFMaskAndPCLKMask        ' Combine those pixels.   
                            or      LNThirdPartBuffer,      LNFourthPartBuffer           '
                            waitpeq LNHREFMaskAndPCLKMask,  LNHREFMaskAndPCLKMask        '
                            or      LNFirstPartBuffer,      LNThirdPartBuffer            '
                            waitpeq LNHREFMaskAndPCLKMask,  LNHREFMaskAndPCLKMask        ' Store [4 1 2 3]. ROR 8 = [3 4 1 2].
    LNStorePixelModify      mov     (LNPixelStorage - 1),   LNFirstPartBuffer            ' 
                            waitpeq LNHREFMaskAndPCLKMask,  LNHREFMaskAndPCLKMask        '                   
                            djnz    LNColumnCounter,        #LNStorePixelLoop            '
    
    
    

    The data gets stored in a 80 long array.

    This code works...

    But, I have to support YUV422 now. In this mode the first byte is Y then the next byte is U, then Y again, and the V. The above code will only grab the YU componets for every pixel. So... by using the MOVI/MODD/MOVS instructions I will be able to make the loop more simple.
                            mov     LNRowCounter,           #_CAMERA_V_WIN               ' Setup for the next frame.
                            waitpeq LNVSYNCMask,            LNVSYNCMask                  '
                                                   
    LNGrabberLineLoop       mov     LNColumnCounter,        #(_CAMERA_H_WIN)         ' Setup for the pixel storage loop.
                            movd    LNStorePixelModify,     #(LNPixelStorage)        '
    ' //////////////////////Store Pixel Unlocked/////////////////////////////////////////////////////////////////////////////////// 
                            
                            waitpne LNHREFMask,             LNHREFMask                   ' Wait for frame end.
                            mov     phsa,                   #0                           '
    LNStorePixelLoop        waitpeq LNHREFMaskAndPCLKMask,  LNHREFMaskAndPCLKMask        ' Grab first pixel.
                            movs    LNBufferCounter,        ina                          '                        
                            waitpeq LNHREFMaskAndPCLKMask,  LNHREFMaskAndPCLKMask        '
                            movd    LNBufferCounter,        ina                          '
                            waitpeq LNHREFMaskAndPCLKMask,  LNHREFMaskAndPCLKMask        ' Grab second pixel.
                            nop                                                          '
                            waitpeq LNHREFMaskAndPCLKMask,  LNHREFMaskAndPCLKMask        '
                            movi    LNBufferCounter,        ina                          '
                            waitpeq LNHREFMaskAndPCLKMask,  LNHREFMaskAndPCLKMask        ' Grab thrid pixel.
    LNStorePixelModify      mov     LNPixelStorage,         LNBufferCounter              '
                            waitpeq LNHREFMaskAndPCLKMask,  LNHREFMaskAndPCLKMask        '
                            add     LNStorePixelModify,     #1                           '
                            
                            waitpeq LNHREFMaskAndPCLKMask,  LNHREFMaskAndPCLKMask        '
                            nop                                                          '
                            waitpeq LNHREFMaskAndPCLKMask,  LNHREFMaskAndPCLKMask        '
                            djnz    LNColumnCounter,        #LNStorePixelLoop            ' 
    
    
    

    This is much better now. I have plenty of time during the three lines of video data that I skip to unpack and process the data. Grabbing it is the hard part.

    There is only one problem with this code change and it is that my array will now be 160 longs instead of 80 longs.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-12-26 17:10
    Is there any way that you could change the pixel clock to 10 MHz, in synchrony with the system clock? That way, you could avoid the waitpeqs and do some work there instead.

    -Phil
  • KyeKye Posts: 2,200
    edited 2011-12-26 19:34
    Nah, 12Mhz is the next step. That's too fast. I prefer having the waitvids actually as they ensure I am locked onto the clock.
  • simonlsimonl Posts: 866
    edited 2011-12-27 08:14
    That reminds me Phil; what ever happened to PropCAM?
  • PublisonPublison Posts: 12,366
    edited 2011-12-27 09:19
    simonl wrote: »
    That reminds me Phil; what ever happened to PropCAM?

    Hush!! Phil doesn't want to talk about it. :)
Sign In or Register to comment.