PNut/Spin2 Latest Version (v34Q)

145679

Comments

  • TonyB_ wrote: »
    JonnyMac wrote: »
    Silly question, perhaps, but can I abort a rep block by simply jumping out it?
    Yes.

    Isn't there some catch when the jump is at the end of the rep block?
  • TonyB_ wrote: »
    JonnyMac wrote: »
    Silly question, perhaps, but can I abort a rep block by simply jumping out it?
    Yes.

    Isn't there some catch when the jump is at the end of the rep block?

    If relative jump there is an issue. Search this thread for more info:
    http://forums.parallax.com/discussion/171254/tia-an-interactive-inline-assembler-for-taqoz
  • Would it be difficult to add a "Get Hardware Version" feature to the command line interface?

    Also, I guess it's time to change that menu option text to "Identify Hardware", like Prop Tool, right?
  • The top 16KB of hub contains the ROM code at boot time. That code contains constants that can be used to determine Rev A or Rev B chips. There is no difference from Rev B to Rev C except the ADC internal track cut and I guess that could be determined by code.
  • That feature is handy for me when I connect a new board to a PC.
    Let's me know if it's alive or not...
  • RaymanRayman Posts: 10,485
    edited 2020-03-19 - 14:24:45
    It'd be nice to have a way of reserving memory, but not initializing it.
    I've got some big arrays that I'm sure slow down the compile and load process.

    The stack/free mechanism in Spin1 can work, but kind of a pain. I don't think it's used much...

    Be nicer if you could declare arrays in a DAT section that are just reserved, not initialized...
    Sorta like RES in PASM...

    Maybe a keyword like "stack"? Like this:
    DAT 'graphics demo data
    
    'Making these 4x bigger for super graphics demo
    BitmapTiles             stack    $aaaa5555[16*x_tiles*y_tiles*4]  'this is tile data working buffer
    DisplayTiles            stack    $11110[16*x_tiles*y_tiles*4]  'this is tile data that is being displayed
    

    or, maybe use "*"
    DAT 'graphics demo data
    
    'Making these 4x bigger for super graphics demo
    BitmapTiles             long*    $aaaa5555[16*x_tiles*y_tiles*4]  'this is tile data working buffer
    DisplayTiles            long*   $11110[16*x_tiles*y_tiles*4]  'this is tile data that is being displayed
    
  • cgraceycgracey Posts: 12,677
    edited 2020-03-19 - 14:54:34
    I just posted a new v34o at the top of this thread.

    I've declared lots of symbols in the compiler for smart pins and streamer modes. The symbols are listed in the doc file, towards the end.

    Now, if you want to make a 15k-high / strong-low pin, you can do this:
    '
    ' Give pin 15k pull-up, TESTP can be used to read pin
    '
            WRPIN   ##p_high_15k,#pin    'select pull-up
            DRVH    #pin                 'make pin high to enable pull-up
    

  • cgracey wrote: »
    I've declared lots of symbols in the compiler for smart pins and streamer modes. The symbols are listed in the doc file, towards the end.
    Looking good. I like the included bit-field parameter labelling. That's something I should've had in my constants list.

  • In the Spin2 documentation, under "Program Structure", there's a minimal PASM-only program:
    loop DRVRND #56 ADDPINS 7 'write a random pattern to P63..P56
         WAITX ##clkfreq_/10 'wait 1/10th of a second, loop
         JMP #loop
    
    This works...

    However, if you try to use clkfreq_ in a Spin2/PASM program, the value seems to always be set to 20_000_000 rather than the actual clock frequency. Bug? My misinterpretation of the documentation? Or do I have to use hub location $44 to get the clock frequency in a Spin2/PASM program?

  • cgraceycgracey Posts: 12,677
    edited 2020-03-21 - 01:00:07
    wmosscrop wrote: »
    In the Spin2 documentation, under "Program Structure", there's a minimal PASM-only program:
    loop DRVRND #56 ADDPINS 7 'write a random pattern to P63..P56
         WAITX ##clkfreq_/10 'wait 1/10th of a second, loop
         JMP #loop
    
    This works...

    However, if you try to use clkfreq_ in a Spin2/PASM program, the value seems to always be set to 20_000_000 rather than the actual clock frequency. Bug? My misinterpretation of the documentation? Or do I have to use hub location $44 to get the clock frequency in a Spin2/PASM program?

    _RCFAST (20MHz) is the default.

    Add this line to your program:

    CON _clkfreq = 250_000_000

    Then, you can use CLKMODE_ in a HUBSET instruction to set the mode:

    HUBSET ##clkmode_ & !3
    WAITX ##20_000_000
    HUBSET ##clkmode_

  • JonnyMacJonnyMac Posts: 6,595
    edited 2020-03-21 - 06:46:04
    I'm struggling with the Cycles/Pulse smart pin mode. I know that it works because I can see it work through TAQOZ.

    This is what I'm trying to make run.
      m := P_OE | P_PULSE                                           ' %01_00100_0
      x := (1000 << 16) | 2000                                      ' 5us high, 5us low @200MHz
      y := 8                                                        ' 8 pulses
     
      pinstart(32, m, x, y)
    
    Nothing on the 'scope (which I setup using a simple loop with pinh/pinl). So, I tried this:
      m := P_OE | P_PULSE                                           ' %01_00100_0
      x := (1000 << 16) | 2000                                      ' 5us high, 5us low @200MHz
      y := 8                                                        ' 8 pulses
      
      org
                            fltl    #32
                            wrpin   m, #32
                            wxpin   x, #32
                            wypin   y, #32
                            drvl    #32
      end
    
    Still nothing. Am I missing something in the mode setting?
  • %00100 = pulse/cycle output
    This mode overrides OUT to control the pin output state.
    X[15:0] establishes a base period in clock cycles which forms the empirical high-time and low-time units.
    X[31:16] establishes a value to which the base period counter will be compared to on each clock cycle, as it counts from
    X[15:0] down to 1, before starting over at X[15:0] if decremented Y > 0. On each clock, if the base period counter > X[31:16]
    and Y > 0, the output will be high (else low).
    Whenever Y[31:0] is written with a non-zero value, the pin will begin outputting a high pulse or cycles, starting at the next base
    period.
    Some examples:
    If X[31:16] is set to 0, the output will be high for the duration of Y > 0.
    If X[15:0] is set to 3 and X[31:16] is set to 2, the output will be 0-0-1 (repeat) for the duration of Y > 0.
    IN will be raised when the pulse or cycles complete, with the pin reverting to low output.
    During reset (DIR=0), IN is low, the output is low, and Y is set to zero.

    You need to do a WYPIN after enabling the smart pin to get it going.
  • Roy ElthamRoy Eltham Posts: 2,801
    edited 2020-03-21 - 07:40:07
    JonnyMac,
    You need to set y after allowing the pin to run for pulse mode. y is forced to 0 until you let it run.

    Edit: Chip beat me! :D
  • Thanks, guys, that works.
  • In the Spin2 documentation, under "Program Structure", there's a minimal PASM-only program:
    loop DRVRND #56 ADDPINS 7 'write a random pattern to P63..P56
         WAITX ##clkfreq_/10 'wait 1/10th of a second, loop
         JMP #loop
    

    This works because the default clock frequency is 20_000_000.

    However, if you try to use clkfreq_ in a Spin2/PASM, the value seems to always be set to 20_000_000 rather than the actual clock frequency. Bug? MiOr do I have to use hub location $44 to get the clock frequency in a Spin2/PASM program?
    cgracey wrote: »
    wmosscrop wrote: »
    In the Spin2 documentation, under "Program Structure", there's a minimal PASM-only program:
    loop DRVRND #56 ADDPINS 7 'write a random pattern to P63..P56
         WAITX ##clkfreq_/10 'wait 1/10th of a second, loop
         JMP #loop
    
    This works...

    However, if you try to use clkfreq_ in a Spin2/PASM program, the value seems to always be set to 20_000_000 rather than the actual clock frequency. Bug? My misinterpretation of the documentation? Or do I have to use hub location $44 to get the clock frequency in a Spin2/PASM program?

    _RCFAST (20MHz) is the default.

    Add this line to your program:

    CON _clkfreq = 250_000_000

    Then, you can use CLKMODE_ in a HUBSET instruction to set the mode:

    HUBSET ##clkmode_ & !3
    WAITX ##20_000_000
    HUBSET ##clkmode_

    I'm trying to determine the current clock frequency, not set it...
  • wmosscrop wrote: »
    I'm trying to determine the current clock frequency, not set it...
    Chip has a section on system clock setting at the end of the spin2 document. It mentions "clkmode" and "clkfreq" for actively set variables. Note there's no underscore in variable names. And, yes, they are at fixed hubram addresses $40 and $44.

  • Just found the Spin2 docs have not read yet. Any major chanages??
    @evanh
  • I assume you mean change from spin1. I've not used either language so have very little knowledge.
  • Just found the Spin2 docs have not read yet. Any major changes??
    Some changes from Spin1 and some behavioral changes that are getting documented in the "Tricks and Traps" thread.
    -- https://forums.parallax.com/discussion/169069/p2-tricks-traps-differences-between-p1-reference-material-only/p1
  • wmosscropwmosscrop Posts: 338
    edited 2020-03-22 - 23:39:37
    Underscores in constants from obj references are treated like underscores in constant values. In other words, they are placeholders rather than characters in the constant name:

    testcon.spin2:
    con
     TEST_CONSTANT = 0
    pub dummy()
    
    testcon2.spin2:
    obj
      testcons : "TestCon"
    pub start() | x
      x := testcons.T_E_S_T_CONSTANT
    
    The above will compile, even though there are extra underscores in the constant name.
    A reference to testcons.TESTCONSTANT wlll also compile.
    This doesn't seem to affect constants defined in the same spin2 file.

    Edit:
    References to nonexistent constants in obj references will be replaced with a zero value rather than raising a compile error.
  • wmosscropwmosscrop Posts: 338
    edited 2020-03-22 - 19:35:57
    Can anyone else duplicate this on their P2 eval board?
    CON
      _clkfreq = 200_000_000
    
    PUB Example()
      waitms(3000)  ' Wait for all led's to go out
    
      pinwrite(56, 0) 
    
      dira[1] := 0	' This causes the led for pin 56 to go out after about 1 second, 
    		' even though we will be executing the repeat loop below
    		' If you comment out this line, the led will stay on
    
      pinwrite(57, 0)
    
      repeat
        pintoggle(58)
        waitms(100)
    
    The led for pin 56 should stay on regardless of the direction of pin 1. It appears that there's a strange delayed side effect for the dira assignment. Other pins for the dira assignment (I've tried only a few, such as 0, 2, and 20, along with dirb assignments) don't seem to cause this issue.

    Or maybe my board is messed up? Or I'm messed up?

    Edit:

    It appears that I'm using dira[1] incorrectly, it should be dira.[1].
  • AribaAriba Posts: 2,255
    edited 2020-03-22 - 21:49:05
    dira[1] := 0 is the same as dirb := 0. You just set the direction of pin 56 to input (and the direction of all the other pins of port B )
    If you want to write bit 1 of DIRA then in Spin2 you need:
    dira.[1] := 0

    Andy
  • cgraceycgracey Posts: 12,677
    edited 2020-03-25 - 04:17:13
    I am making a self-calibrating 8-channel ADC object that starts a PASM program in the registers not used by the Spin2 interpreter. It returns millivolts per each channel for Spin2 to use without any extra massaging. I discovered that I must shield CORDIC operations within the interpreter from interrupts, so that the PASM code running on interrupts can also use the CORDIC. Should have this working tomorrow. Now I must add several STALLI/ALLOWI instructions into the Spin2 interpreter and move things around to make everything fit again.
  • That sounds very useful, Chip. It'll be nice to have that built-in
  • Making cooperative from pre-emptive.

  • Chip,
    Just pondering interrupts some more, it dawned on me that any stalled instruction can't be interrupted. Not just the WAITxxx instructions. So, for example, an XCONT instruction waiting on the streamer will also put a hold on IRQ response times.

  • cgraceycgracey Posts: 12,677
    edited 2020-03-26 - 01:29:27
    evanh wrote: »
    Chip,
    Just pondering interrupts some more, it dawned on me that any stalled instruction can't be interrupted. Not just the WAITxxx instructions. So, for example, an XCONT instruction waiting on the streamer will also put a hold on IRQ response times.

    True, but those kinds of instructions aren't used in the interpreter. Everything that waits does loops.

    I found and fixed a problem last night. I was using the CORDIC within my interrupt routine and I noticed it was interfering with the interpreter operation. So, I had to put STALLI and ALLOWI around interpreter routines that use the CORDIC. Now, there's not interference, but it has lengthened the interrupt-to-ISR time considerably - around 60 clocks for single CORDIC operations. WAITMS/WAITUS/GETSEC do double CORDIC operations, so they cause double the delay. I'm going to break those CORDIC sequences into two parts, where they each have their own STALLI/ALLOWI and a NOP in-between, if necessary, to allow ISR's better time granularity. I will post the latest PNut.exe soon. I've added lots of constant symbols for things that need them.
  • evanhevanh Posts: 9,044
    edited 2020-03-26 - 03:44:54
    cgracey wrote: »
    evanh wrote: »
    ... for example, an XCONT instruction waiting on the streamer will also put a hold on IRQ response times.
    True, but those kinds of instructions aren't used in the interpreter.
    Ah, I was thinking more about the prop2 document:
    When an interrupt event occurs, certain conditions must be met before the interrupt branch can happen:
    - ALTxx / CRCNIB / SCA / SCAS / GETXACC / SETQ / SETQ2 / XORO32 / XBYTE must not be executing
    - AUGS must not be executing or waiting for a S/# instruction
    - AUGD must not be executing or waiting for a D/# instruction
    - REP must not be executing or active
    - STALLI must not be executing or active
    - The cog must not be stalled in any WAITx instruction

    That last point should be extended.

  • Okay, here I go again...

    file testaddr.spin2:
    PUB Start()
    
    file testaddrmain.spin2:
    obj
      testaddr : "testaddr"
    
    var
       long core
    
    pub start()
      pinwrite(56 addpins 7, !((@core) >> 16))
      repeat
    

    Based on this (on a P2 eval board), the address of core has its uppermost 16 bits set to $xx20, which is an address > 2MB.
    If you comment out the reference to testaddr, then the address of core has the uppermost bits set to $xx00, which is what I would expect.
    Bug? Feature?

  • cgraceycgracey Posts: 12,677
    edited 2020-03-28 - 11:52:14
    wmosscrop wrote: »
    Okay, here I go again...

    file testaddr.spin2:
    PUB Start()
    
    file testaddrmain.spin2:
    obj
      testaddr : "testaddr"
    
    var
       long core
    
    pub start()
      pinwrite(56 addpins 7, !((@core) >> 16))
      repeat
    

    Based on this (on a P2 eval board), the address of core has its uppermost 16 bits set to $xx20, which is an address > 2MB.
    If you comment out the reference to testaddr, then the address of core has the uppermost bits set to $xx00, which is what I would expect.
    Bug? Feature?

    So, this is because VBASE[31:20] holds the index of the first PUB to execute in a method pointer, which mechanism is used to start Spin2, both on app launch and COGSPIN launch. It's harmless, but annoying. I will see about getting rid of this anomaly. Thanks for pointing this out, Wmosscrop.

    EDIT: Only the lower 20 bits of addresses matter in Spin2. The upper bits get ignored by the interpreter. But I will get this cleaned up.
Sign In or Register to comment.