Shop OBEX P1 Docs P2 Docs Learn Events
Prop2 FPGA files!!! - Updated 2 June 2018 - Final Version 32i - Page 69 — Parallax Forums

Prop2 FPGA files!!! - Updated 2 June 2018 - Final Version 32i

16667697172160

Comments

  • Rayman wrote: »
    ... uses "@" with REP, so I guess that's how it's supposed to be. Seems a little strange though...

    The D value in the REP instruction is a unsigned 9 bit offset to the end of the REP block.
    Only positive offsets are allowed for REP instructions, so a @ instead of a #@ might be Chip's Pnut trick to solve this?
  • cgraceycgracey Posts: 14,155
    ozpropdev wrote: »
    Rayman wrote: »
    ... uses "@" with REP, so I guess that's how it's supposed to be. Seems a little strange though...

    The D value in the REP instruction is a unsigned 9 bit offset to the end of the REP block.
    Only positive offsets are allowed for REP instructions, so a @ instead of a #@ might be Chip's Pnut trick to solve this?

    @ used for D in REP sets the number of instructions to repeat, minus one, based on a forward label after the instructions. REP must be encountered before the instructions to repeat, so a reverse branch is not possible.
  • rjo__rjo__ Posts: 2,114
    I have serial code that works... it just doesn't work the way I think it should, regarding

    pm_camtx long %0000_0000_000_0000000000000_01_11110_0 'async tx mode.


    In Chip's smartpin_serial_turnaround.spin2 from v13, he waits for an empty tx buffer and then uses wypin to send a byte to tx pin (pin0).
    
    .full		
    
                    testin #0	wc	'wait for buffer empty on tx pin
    	if_nc	jmp	#.full
                    wypin	x,#0		'send next byte to tx pin      
    
    

    When I do this, it hangs on me... but the following works fine:
    sendcam_char       
                 
                     testin   #cam_tx wc
            if_c    jmp     #sendcam_char
                   
                     WYPIN  camTx_char,#cam_tx
                     akpin   #cam_tx 
                   
                    ret
    

    notice... the condition (if_c) is wrong and I have an akpin in there, where I don't think I need it anymore.
    Also... somewhere I got the idea that the bit period had a new calculation:

    cambitper long (sys_clk/cambaud_rate)*$10_000 & $FFFFFC00 | 7 'sys_clk/baud_rate + bits-1

    when I use this, I get an extra byte (=128) sent out through tx_pin following the correct byte...
    but when I go back to the prior calculation for the bit period:

    cambitper long (sys_clk/cambaud_rate)<<16 + 7 'sys_clk/baud_rate + bits-1

    everything is as it should be, no extra byte.

    I thought maybe I had accidentally used the wrong .rbf file, but I just re-loaded the image and the behavior is the same.

    I have included a zip of the full code. The routine starts at line 866.







  • rjo__rjo__ Posts: 2,114
    edited 2016-11-15 05:24
    hmmmmmm....
  • The Tx/Rx NCO also has fractional adjust now.
    X[15:10] establishes the number of fractional clocks in a bit period.
    	baudrate = 115_200
    	nco = (sys_clk / baudrate) * $1_0000 & $FFFFFC00 
    	nco_f = (sys_clk - ((sys_clk / baudrate) * baudrate)) * 64 / baudrate
    and then 
    	wxpin	##nco | nco_f << 10 |7,#tx_pin
    
  • rjo__rjo__ Posts: 2,114
    Thanks
  • rjo__rjo__ Posts: 2,114
    edited 2016-11-17 01:58
    Still having the same issue. My setup is a serial line between a P1 and P2... using pins: P1 rx=5; tx=4 ......... P2 rx=33 tx=32.

    The P2 receiver works exactly as expected... same wc condition on testin and no akpin required.
    But to transmit I still have to use the wrong condition and put an akpin in... it works,
    but I'm confused as why.

    Also... when the P2 starts transmitting for the first time, it seems to throw out one extra byte. I have tried
    various ways to get rid of this byte to no avail.... seems to be something at start-up.

    Thanks

    Rich

    edit... on the P1 I have both rx and tx tied to ground.
    edit #2... P1 and P2 share common ground. In the P2 code... the delay waitx ##160000 is required because I'm using ser.rxtime(1) on the P1 side.
  • Rich
    This is what I use based on the P2 docs for async Tx.
    RDPIN/RQPIN with WC always returns the ‘busy’ flag into C. This is useful for knowing when a transmission has completed
    tx_byte		rdpin	status,#tx_pin wc
    	if_c	jmp	#tx_byte
    		wypin	char,#tx_pin
    
  • garryjgarryj Posts: 337
    edited 2016-11-17 03:00
    @rjo__
    I see you're using TESTIN on the tx pin -- in this case C is set when the buffer empties.
    1. Wait for an output word to be buffered via WYPIN, then set the ‘buffer-full’ and ‘busy’ flags.
    2. Move the word into the shifter, clear the ‘buffer-full’ flag, and raise IN.
    dtx_char
    		testin	#TX			wc	' Wait for tx ready
    	if_nc	jmp	#dtx_char
    		and	dtx, #$ff			' Ensure limited to extended ASCII space
    		wypin	dtx, #TX
    		ret
    
    Edit: is there any speed difference between using TESTIN or RDPIN/RQPIN? I know the latter is two clocks -- is TESTIN the same?
  • One small "speed tweak" is
    tx_byte		testin	#tx_pin wc
    	if_nc	jmp	#tx_byte
    
    can be replaced with
    
    txbyte		jnp	#tx_pin,#txbyte
    
  • Ah, that's another one of them shiny new tools in the v13 toolbox :smile:
  • garryj wrote: »
    Ah, that's another one of them shiny new tools in the v13 toolbox :smile:
    JP/JNP goes all the way back to V1, I just forget to use it! :lol:
  • rjo__rjo__ Posts: 2,114
    Every clock counts:) nice.
    ozpropdev wrote: »
    One small "speed tweak" is
    tx_byte		testin	#tx_pin wc
    	if_nc	jmp	#tx_byte
    
    can be replaced with
    
    txbyte		jnp	#tx_pin,#txbyte
    

    I don't have a problem using rdpin, but when I use the above code, it hangs and I have to throw an akpin to make if_c work:)
    Remember... this is going straight to a Prop1.... not sure that it matters, but that is what I'm doing.

    The reason I persist is that it just doesn't seem right... and I don't think it is my code.
  • Rich
    I made a few tweaks to your P2 code, see if it works.
    I also noticed that you have the Rx mode set for output, this can cause grief too.
  • rjo__rjo__ Posts: 2,114
    Thank you very much. Yes, RdPin wc gets rid of the akpin!!!

    The initial extra byte is still there. It occurs any time I recompile the P2 code.

    Here is a consecutive list of the extra first values... each collected after a recompile:

    10000000
    11000000
    11111100
    11110000
    00110000
    11111000
    11111111
    11110000
    00110000
    11000000
    11110000
    11100000
    11111111
    11111000

    Altogether I looked at over 20 values and didn't see a 101 pattern, which you would expect if the value was random. The value seen after power cycling the P123 board was variable.
  • jmgjmg Posts: 15,173
    rjo__ wrote: »
    Also... when the P2 starts transmitting for the first time, it seems to throw out one extra byte. I have tried
    ...
    The initial extra byte is still there. It occurs any time I recompile the P2 code.

    Here is a consecutive list of the extra first values... each collected after a recompile:

    10000000
    11000000
    11111100
    11110000
    00110000
    11111000
    11111111
    11110000
    00110000
    11000000
    11110000
    11100000
    11111111
    11111000

    Altogether I looked at over 20 values and didn't see a 101 pattern, which you would expect if the value was random. The value seen after power cycling the P123 board was variable.
    Can you clarify - is that extra byte there on any Reset too - you only mention recompile and Power cycling ?
    How does it re-boot - from SPI or via serial loader ?
    Is this testing a separate smart pin, or sharing the one used for Serial Boot ?
    Can anyone else confirm an extra byte when P2 starts transmitting ?

  • rjo__rjo__ Posts: 2,114
    Yes also happens on reset.
    My setup is serial between a P1 and P2... using pins: P1 rx=5; tx=4 ......... P2 rx=33 tx=32.
  • rjo__rjo__ Posts: 2,114
    edited 2016-11-19 01:17
    For all I know it could be part of the serial protocol:)
  • evanhevanh Posts: 15,921
    Rich,
    It's probably a simple line transition, as the pins get configured, that is being interpreted as a start bit.
  • RaymanRayman Posts: 14,652
    I was just admiring jump table code in garryl's USB code for processing commands and calling whatever subroutine is needed:
                    mov     dtmp, devent                    ' Save the eventID
                    min     dtmp, #1
                    max     dtmp, #D_END
                    sub     dtmp, #1                        ' Jump table is zero-based
                    add     dtmp, #devent_jmp
                    push    #devent_exit                    ' Event handlers return here
                    jmp     dtmp
    devent_jmp
                    jmp     #htx_asciiz                     ' Host requested string output to terminal
                    jmp     #htx_break                      ' Send host debug data to terminal, then halt
                    jmp     #htx_dbg_data                   ' Send host debug data to terminal
                    jmp     #htx_hexdump                    ' Dump raw data to terminal
                    jmp     #connect_info
                    jmp     #dev_disconnect
                    jmp     #parse_dev_desc                 ' Parse string data in the device descriptor
                    jmp     #parse_con_desc                 ' Parse config descriptor to determine if it's a known device class
                    jmp     #get_txn_result                 ' Get DTX_RESULT event data and jump to IRP result handler routine
                    jmp     #get_tx_hresult                 ' DTX_HRESULT is a way for the host to route processing results to the terminal
                    loc     ptra, #@sz_jmptbl_err           ' DEBUG: Jump table beyond limit
                    call    #dtx_asciiz
    devent_exit
                    wrlut   #D_READY, #D_EVENT              ' Ready for next event posting
                    ret
    

    It's very efficient. Like how it pushes the return address so can do a JMP with subroutine doing a RET that is basically tricked into returning to the address that was pushed.

    The simple way I was doing it works, but uses much more space:
    'Process command
                  cmp       garg0,#DrawCharacter_ wz
            if_z  jmp       #DrawCharCmd
                  cmp       garg0,#ClearScreen_ wz
            if_z  jmp       #ClearScreenCmd
                  cmp       garg0,#DrawString_ wz
            if_z  jmp       #DrawStringCmd
                  cmp       garg0,#DrawFilledRectangle_ wz
            if_z  jmp       #DrawFilledRectangleCmd              
                  cmp       garg0,#DrawLine_ wz
            if_z  jmp       #DrawLineCmd
                  cmp       garg0,#DrawCircle_ wz
            if_z  jmp       #DrawCircleCmd
                  cmp       garg0,#DrawBMP_ wz
            if_z  jmp       #DrawBMPCmd                    
    GEDone                            
                  jmp       #GELoop
    
  • This would be a good place to use the JMPREL instruction
                    push    #devent_exit                    ' Event handlers return here
                    jmprel  devent
    
    devent_jmp	ret			'not used
                    jmp     #htx_asciiz                     ' Host requested string output to terminal
                    jmp     #htx_break                      ' Send host debug data to terminal, then halt
                    jmp     #htx_dbg_data                   ' Send host debug data to terminal
                    jmp     #htx_hexdump                    ' Dump raw data to terminal
                    jmp     #connect_info
                    jmp     #dev_disconnect
                    jmp     #parse_dev_desc                 ' Parse string data in the device descriptor
                    jmp     #parse_con_desc                 ' Parse config descriptor to determine if it's a known device class
                    jmp     #get_txn_result                 ' Get DTX_RESULT event data and jump to IRP result handler routine
                    jmp     #get_tx_hresult  
    
  • ozpropdev wrote: »
    This would be a good place to use the JMPREL instruction
                    push    #devent_exit                    ' Event handlers return here
                    jmprel  devent
    
    devent_jmp	ret			'not used
                    jmp     #htx_asciiz                     ' Host requested string output to terminal
                    jmp     #htx_break                      ' Send host debug data to terminal, then halt
                    jmp     #htx_dbg_data                   ' Send host debug data to terminal
                    jmp     #htx_hexdump                    ' Dump raw data to terminal
                    jmp     #connect_info
                    jmp     #dev_disconnect
                    jmp     #parse_dev_desc                 ' Parse string data in the device descriptor
                    jmp     #parse_con_desc                 ' Parse config descriptor to determine if it's a known device class
                    jmp     #get_txn_result                 ' Get DTX_RESULT event data and jump to IRP result handler routine
                    jmp     #get_tx_hresult  
    

    Out of curiousity, what is the purpose of the unused ret instruction?
  • jmgjmg Posts: 15,173
    Seairth wrote: »
    Out of curiousity, what is the purpose of the unused ret instruction?

    I think that is for a 1-based index.
    I was going to mention the sub dtmp, #1 in the original, could have been replaced with an empty table slot, for the same size, but faster overall.
  • jmg wrote: »
    Seairth wrote: »
    Out of curiousity, what is the purpose of the unused ret instruction?

    I think that is for a 1-based index.
    I was going to mention the sub dtmp, #1 in the original, could have been replaced with an empty table slot, for the same size, but faster overall.
    That's correct, in this case a zero index is unused/invalid.

    I see great potential for JMPREL in things like bytecode interpreters (SPIN2) for rapid instruction group decoding. :)

  • ozpropdev wrote: »
    jmg wrote: »
    Seairth wrote: »
    Out of curiousity, what is the purpose of the unused ret instruction?

    I think that is for a 1-based index.
    I was going to mention the sub dtmp, #1 in the original, could have been replaced with an empty table slot, for the same size, but faster overall.
    That's correct, in this case a zero index is unused/invalid.

    I see great potential for JMPREL in things like bytecode interpreters (SPIN2) for rapid instruction group decoding. :)

    Okay. I was just making sure there wasn't a caveat with JMPREL.
  • RaymanRayman Posts: 14,652
    JMPREL does look good. Guess this is what it is intended for...
  • RaymanRayman Posts: 14,652
    edited 2016-12-04 14:13
    I just had a very strange thing happen, was driving me crazy.

    All of the sudden, my GUI w/ USB code stopped working.
    Well, the USB part stopped working anyway.

    Spent an hour trying to figure out what was wrong with the code.
    Finally decided it had to be a hardware fault.

    Sure enough, cycled power on my P123-A9 and then it started working again.

    I'm guessing that somehow the shared cog LUT between cogs 6 and 7 got messed up over time. Not exactly sure how that can happen though...
  • RaymanRayman Posts: 14,652
    Happened again... Knew what to do this time. Cycled power on P123 and all better.

    Is there any way code can mess up P2V in a way that survives reprogramming?
  • jmgjmg Posts: 15,173
    Rayman wrote: »
    Happened again... Knew what to do this time. Cycled power on P123 and all better.

    Is there any way code can mess up P2V in a way that survives reprogramming?
    Do you mean FPGA reprogramming or just P2 code area reprogramming ?
    I guess a simple P2 reset also fails ?
    Is there a way to reload the FPGA bitstream, without cycling the power ? (just to exclude something other than FPGA)

    If the issue needs a FPGA reset, as opposed to a P2 reload/reset, then maybe there is some logic that is not properly P2-reset covered ?
    Is RAM also preloaded on FPGA reset ? That may be another way to get similar symptoms.
    Adding/removing a clear all ram/fill random block should check that ?
  • Rayman wrote: »
    Happened again... Knew what to do this time. Cycled power on P123 and all better.

    Is there any way code can mess up P2V in a way that survives reprogramming?
    The USB code is likely the instigator of this, as I've been down the power-cycle road on occasion. I don't doubt that it is programmer error that starts the ball rolling, but I have yet to find a scenario that will reliably reproduce it, yet. Whatever it is appears to lobotomize the USB smart pins, and when it's in this state, neither a code reload or hardware reset via the PB0 button on the Prop123-A9 board prior to reload works.

    I got the board into this lobotomized state a bit ago, but this time I kept the board powered on and used the PGM/RUN switch and PX.exe to reload the FPGA image, then reloaded the code, and things were good. So it looks like whatever is going on is having an adverse effect on the FPGA image.
Sign In or Register to comment.