Shop OBEX P1 Docs P2 Docs Learn Events
A question for Kye (and anyone else!) — Parallax Forums

A question for Kye (and anyone else!)

Dr_AculaDr_Acula Posts: 5,484
edited 2010-12-30 19:38 in Propeller 1
After a couple of months writing an IDE for Catalina, I'm now beginning the fun part, which is to translate Spin code into C. I have a syntax that allows PASM and C code to be glued together in the same way Spin and PASM can share common variables. I'm also doing this in external memory, so we can do fun things like wipe the entire hub memory and then fill it with new values, and load and reload cogs from within code as often as needed without having to worry about running out of memory.

As the first object to translate, I'd like to have a go at doing your PixEngine. There is some very clever code in the Start section and it essentially takes a value "pingroup" which is 0,1,2 or 3 and translates it into some other values. I'd initially probably only use pingroup 2 (pins 16 to 23 for VGA) so the values this calculates could even be simple constants.

I've taken the code and put in some comments. Most things would translate to C fairly easily, but I can't seem to find a bit of code for a 32 bit rotate in C. Given that this just spits out a few constants, I was wondering what the following code produces if the input value is "2"

The comments are mine and the math might not be correct!
PUB PIXEngineStart(pinGroup) '' 7 Stack Longs

'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'' // Starts up the PIX driver running on a cog.
'' //
'' // Returns true on success and false on failure.
'' //
'' // PinGroup - Pin group to use to drive the video circuit. Between 0 and 3.
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

  PIXEngineStop
  if(chipver == 1)

    pinGroup := ((pinGroup <# 3) #> 0) ' limit max to 3 and min to 0. Using pingroup 2
    directionState := ($FF << (8 * pinGroup)) ' $00_FF_00_00 for group 2
    videoState := ($30_00_00_FF | (pinGroup << 9)) ' 2 is %10 so shift left 9 is %00000100_00000000 so ? $30_00_04_FF

    pinGroup := constant((25_175_000 + 1_600) / 4) ' this changes pingroup to ? 6294150 
    frequencyState := 1

    repeat 32
      pinGroup <<= 1 ' shift left ie multiply by 2
      frequencyState <-= 1 ' bitwise rotate left, in C this will be more complex, eg this is a byte rotate right a = (a >> n) || (a << (8-n))
      if(pinGroup => clkfreq) ' if 6294150 more than or equal to clock frequency
        pinGroup -= clkfreq  ' pingroup := pingroup - clkfreq
        frequencyState += 1 ' add 1 to frequencystate

    displayIndicatorAddress := @displayIndicator
    syncIndicatorAddress := @syncIndicator
    cogNumber := cognew(@initialization, @displayBuffer)
    result or= ++cogNumber

Comments

  • KyeKye Posts: 2,200
    edited 2010-12-30 11:33
    I'm just reusing the value of pinGroup for a calculation there.

    The input PinGroup is only relevant for these lines:


    pinGroup := ((pinGroup <# 3) #> 0) ' limit max to 3 and min to 0. Using pingroup 2
    directionState := ($FF << (8 * pinGroup)) ' $00_FF_00_00 for group 2
    videoState := ($30_00_00_FF | (pinGroup << 9)) ' 2 is %10 so shift left 9 is %00000100_00000000 so ? $30_00_04_FF

    After that I'm just using the variable to hold another number.

    All of this below is just a 64/32 bit divide. It effectively does ... ((((25_175_000 + 1_600) / 4) << 32) / clkfreq) ... of course you can't write that because it will overflow.

    pinGroup := constant((25_175_000 + 1_600) / 4) ' this changes pingroup to ? 6294150
    frequencyState := 1

    repeat 32
    pinGroup <<= 1 ' shift left ie multiply by 2
    frequencyState <-= 1 ' bitwise rotate left, in C this will be more complex, eg this is a byte rotate right a = (a >> n) || (a << (8-n))
    if(pinGroup => clkfreq) ' if 6294150 more than or equal to clock frequency
    pinGroup -= clkfreq ' pingroup := pingroup - clkfreq
    frequencyState += 1 ' add 1 to frequencystate
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2010-12-30 13:40
    Thanks ++. Even 32 bits is not enough for a big divide.

    So to clarify, we have (25_175_000 + 1_600) / 4 and given the way the brackets are, this is 6294150. Then multiply by 2^32 so this is 6294150 * 4294967296 which is 27033168406118400, then divide by 80000000 and I get 337914605.07648

    That doesn't seem right as there is a decimal point (unless windows calculator can't handle these big numbers either). Also I'm not sure what frequencystate comes out at.

    I might try running this through a new spin program and see what the answers are.

    I gather that pingroup is just a temporary variable - the actual answer is in frequencystate?

    Addit: I ran the code and got 337914606 which is one more than the above answer when rounded to an integer. So I'll stick with that value. I could put this in as a constant as clkfreq will always be 80000000 on this board.

    Back to coding!
  • KyeKye Posts: 2,200
    edited 2010-12-30 14:19
    Spot on! Yes, the math the loop does rounds up.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2010-12-30 14:55
    And just to double check that videostate is $30_00_04_FF with pin group 2?
  • KyeKye Posts: 2,200
    edited 2010-12-30 16:21
    Yes.

    10 Characters...
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2010-12-30 19:38
    Thanks for that. 6 hours of solid coding and I have success! Your 160x120 vga 64 color driver now runs in C. See the Catalina version 2.6 thread for the code and all the steps to get there.

    This opens up a new way of using the propeller. 512k of code space and no limit to the number of cogs any more as you can keep recycling cogs as often as you like. Load cogs from within code, or load them from the sd card. Potentially you could have the whole Obex on an SD card.

    I am very excited!

    And thankyou for your prompt response. I wasn't sure this was going to work when I first started coding it.
Sign In or Register to comment.