Shop OBEX P1 Docs P2 Docs Learn Events
cogserial - fullduplex smart serial using interrupt - Page 3 — Parallax Forums

cogserial - fullduplex smart serial using interrupt

1356

Comments

  • Cluso99 wrote: »
    Looking closer, i am unsure what is not working.

    Are those 8 lines working and you need to find a 5 instruction replacement for them?

    yes, exactly.
  • I am shaving longs off my code and sadly broke my second RX/TX pair while doing so.

    but the first pair is now running up to sysclock baud talking with smartpins to itself. I am not able to get the data from and to HUB that fast because I just do rdbytes and wrbytes. That is the reason I really need some more longs to at least write longs when possible.

    My RX buffers do now use bytes in the LUT while TX is still using Longs for a byte, I even needed to take HEX display out, because of erratic failures depending on code size.

    On the P1 I used FIT 496 to avoid running into special registers, how much space I have in the P2 COG ram? LUT is completely used for buffers, so no space there left.

    I really would like to have this driver to be able to run two pairs of RX and TX and I am almost there, I just need some more longs and find my RXcheck-error on RX2.

    And I really would like to understand the ALTSB instruction

    107 alias Register Indirection EEEE 1001011 001 DDDDDDDDD 000000000 ALTSB D Alter subsequent SETBYTE instruction. Next D field = D[10:2], N field = D[1:0]. 2 same 2 same D
    I do understand that the new destination (my rx2_lut_value register) needs to end up in D[10:2] and the new N field (my #3 in register rx2_byte_index) should end up in D[1:0]


    say I want to make this instruction

    setbyte rx2_lut_value, rx2_char, #3

    out of

    setbyte rx2_lut_value, rx2_char, #2

    or vice versa, does not matter, I just need to somehow change the last parameter which is now a constant and I have it in a register.

    but

    mov rx2_byte_index, #3
    add rx2_byte_index, #rx2_lut_value<<2
    altsb rx2_byte_index
    setbyte 0-0, rx2_char, #0-0

    does not do what I want. What I am doing wrong here.

    clueless,

    Mike
  • msrobotsmsrobots Posts: 3,704
    edited 2019-02-07 10:36
    no I did not, but I still do not understand what I am doing wrong, your example makes not really sense to me.

    I need a

    setbyte rx2_lut_value, rx2_char, #3
    to set the fourth byte of rx2_lut_value to the last 8 bits of rx2_char

    or the first, second or third byte, having the byte number (#3) in a register not as a constant.

    so I need actually
    setbyte rx2_lut_value, rx2_char, rx2_byte_index

    how would

    altsb rx2_head, #rx2_buffer
    setbyte rx2_char

    do that?

    confused,

    Mike
  • evanhevanh Posts: 15,192
    edited 2019-02-07 10:48
    ALTSB+SETBYTE just writes one byte at a time.
    rx2_head is the index into the buffer, starting at 0.
    #rx2_buffer is the start address, a constant, of the buffer itself.

    The ALTSB instruction manipulates both parts of the SETBYTE instruction so that the index becomes byte scaled instead of the native longword scale of cogRAM.

    Pnut has a convenient alias of SETBYTE that only has the byte data parameter. This is purely for pairing with ALTSB.
  • Cluso99Cluso99 Posts: 18,069
    Ok r2_byte_index contains the value of 0-3 and you need 3-0 so
    XOR r2_byte_index,#3

    Now create this as an index into the correct byte position by *8 which is <<3 so
    SHL r2_byte_index,#3

    Now position the byte you read into the correct byte position
    SHL rx2_char,r2_byte_index

    Your bytes value should be zero inthe byte position we are now placing the rx byte into so
    OR rx2_lut_value,rx2_char

    This should work for you i think.
  • ersmithersmith Posts: 5,918
    edited 2019-02-07 13:35
    msrobots wrote: »
    to set the fourth byte of rx2_lut_value to the last 8 bits of rx2_char

    or the first, second or third byte, having the byte number (#3) in a register not as a constant.

    so I need actually
    setbyte rx2_lut_value, rx2_char, rx2_byte_index
    

    OK, my understanding is that you have a single long rx2_lut_value and you want to change byte 0-3 in it. Then I think you would do this by:
      altsb rx2_byte_index, #rx2_lut_value
      setbyte rx2_char
    
    The general form of altsb is "altsb offset, base", where "offset" is the byte offset into the buffer that starts at COG memory address "base". Frequently "base" is a fixed value, so most uses of altsb look like:
      altsb offset, #table
      setbyte value
    

    (Edited to fix a misunderstanding on my part.)
  • msrobotsmsrobots Posts: 3,704
    edited 2019-02-07 11:05
    oh @Cluso99, you are simply cool.

    Just bypassing the setbyte getbyte thing.

    For getbyte I already decided that just shifting and and-ing with $FF is fine and fast, but for setbyte I was unsure what to do.

    Because I can not assume that the byte position in the long where my byte has to go is zero. It isn't. I may have any value.

    The current version takes 8 longs, that need to get beaten down it happens 2 times each for each port, so any long shaved, shaves 4 longs.

    getting the byte out of the long is easy with SHR and AND saves about 5 longs on the getbyte version I have now.

    but how to replace a byte in a long with the index for the byte in a register in less then 8 instructions I now take with cmp and setbyte four times.

    Or how to ALTSB setbyte to change the last parameter, which is a constant and can not be a register.

    I am fighting for every long right now to keep this driver able to run 2 fullduplex ports with buffers in LUT. Would be sad if I need to go down to one fullduplex port.

    Enjoy!

    Mike
  • evanh wrote: »
    ALTSB+SETBYTE just writes one byte at a time.
    rx2_head is the index into the buffer, starting at 0.
    #rx2_buffer is the start address, a constant, of the buffer itself.

    The ALTSB instruction manipulates both parts of the SETBYTE instruction so that the index becomes byte scaled instead of the native longword scale of cogRAM.

    Pnut has a convenient alias of SETBYTE that only has the byte data parameter. This is purely for pairing with ALTSB.

    But I do not want to write a byte into a buffer I want to change one byte in my register.

    do I completely misunderstand setbyte and getbyte?

    more confused,

    Mike
  • evanhevanh Posts: 15,192
    Normally interrupt code will fill or empty a buffer. I was demonstrating the filling action of receiving a character from a smartpin and buffering it.
  • Cluso99Cluso99 Posts: 18,069
    When you receive a byte, initially its in the top 8 bits. You can use this to advantage. Your index is reversed which is another advantage.
    So just shift the index <<3
    Now shift rx2 >> by the index snd now its in the right position for OR into the value.
    Now you also have to and off the byte in value before you do the OR so
    MASK LONG $FF_00_00_00

    MOV tmp,mask
    SHR tmp,index (your index<<3 result above)
    AND value,tmp

    There may be another way to do this too. And the new respin might also have another way too.

    Now, since you have two copies of this code, self modifying code might be better so you have a common routine. Also the respin will support indexing RDLUT/WRLUT ptr instructions too.

    Sorry, i dont have time to look thru all your code atm. Maybe in a week or two.
  • msrobots wrote: »
    But I do not want to write a byte into a buffer I want to change one byte in my register.
    Treat the register as a 4 byte buffer. They're the same thing. In P1 days we could never access anything smaller than a long in COG memory, but now with getbyte/setbyte COG memory is byte addressable, in a way.
  • msrobotsmsrobots Posts: 3,704
    edited 2019-02-07 11:57
    gosh, @evanh

    can you please stop evading my question?

    I am really stuck here and I need to modify a byte inside a given long in a register by replacing it with another byte in the lower 8 bits in another register, having the position of the byte to be replaced in a third register.

    so what I need would be a ALTwhatever instruction to archive

    setbyte rx2_lut_value, rx2_char, rx2_byte_index

    with rx2_byte_index being the content of a register not a constant

    You obviously understand the ALTSB instruction and I don't.

    So please give me some hint how to use it to archive a

    setbyte rx2_lut_value, rx2_char, rx2_byte_index

    to set the byte with the index contained in rx2_byte_index in rx2_lut_value to the content of rx2_char

    I need to replace

    setbyte rx2_lut_value, rx2_char, #xx

    by

    setbyte rx2_lut_value, rx2_char, rx2_byte_index

    and I really hope that you or someone else could give me an answer for that problem, because I am just a couple of longs away from a working driver...

    Enjoy!

    Mike
  • Cluso99Cluso99 Posts: 18,069
    edited 2019-02-07 11:57
    ersmith wrote: »
    msrobots wrote: »
    But I do not want to write a byte into a buffer I want to change one byte in my register.
    Treat the register as a 4 byte buffer. They're the same thing. In P1 days we could never access anything smaller than a long in COG memory, but now with getbyte/setbyte COG memory is byte addressable, in a way.
    And we have LUT, lots of manipulating instructions, and hub accesses do not have to be long aligned. Massive fun ahead :smiley:
  • evanhevanh Posts: 15,192
    ALTxx prefixing instructions are for indexing work. If you only want a singular byte then GETBYTE and SETBYTE by themselves is fine. Forget ALTxx.
  • msrobotsmsrobots Posts: 3,704
    edited 2019-02-07 12:07
    - In P1 days we could never access anything smaller than a long in COG memory, but now with getbyte/setbyte COG memory is byte addressable, in a way.

    Yes, and I really would like to find out a way I can do exactly access a byte in any position in a long in COG memory with setbyte without using a constant for the byte position to replace that
    		cmp	rx2_byte_index,	#0		wz
    	if_z	setbyte rx2_lut_value,	rx2_char, #3
    		cmp	rx2_byte_index,	#1		wz
    	if_z	setbyte rx2_lut_value,	rx2_char, #2
    		cmp	rx2_byte_index,	#2		wz
    	if_z	setbyte rx2_lut_value,	rx2_char, #1
    		cmp	rx2_byte_index,	#3		wz
    	if_z	setbyte rx2_lut_value,	rx2_char, #0
    

    with something shorter

    Mike
  • Maybe something like
            altr    #t
            rol     rx2_byte_index, #3   ' convert to bit index
            altr    #t
            shl     rx2_char, t
            or      rx2_lut_value, t
    

    I suspect ALTI can help with SETBYTE, I've not looked into that instruction yet.
  • evanhevanh Posts: 15,192
    Well using those exact names:
    		altsb	rx2_byte_index, #rx2_lut_value
    		setbyte	rx2_char
    
  • evanh wrote: »
    Well using those exact names:
    		altsb	rx2_byte_index, #rx2_lut_value
    		setbyte	rx2_char
    

    So ALTSB isn't too broken? Seem to be going round in loops here, and I haven't helped!
  • TonyB_TonyB_ Posts: 2,127
    edited 2019-02-07 18:57
    deleted
  • evanhevanh Posts: 15,192
    Tony,
    I think Mike is trying to set the content of rx2_lut_value itself. Without the # there, ALTSB would use the value stored in rx2_lut_value as a cogRAM address.
  • evanh wrote: »
    Tony,
    I think Mike is trying to set the content of rx2_lut_value itself. Without the # there, ALTSB would use the value stored in rx2_lut_value as a cogRAM address.

    Yes, sorry, I misunderstood what Mike was trying to do. Evanh has the right idea, I think.

    To summarize:

    (1) If you're trying to set byte N of register X, do
      altsb N, #X
      setbyte value
    

    (2) If P is a pointer with a COG address in it, and you want to modify byte N of the register P points to, then do:
      altsb N, P
      setbyte value
    
    Note that P is a COG address, so it does not (necessarily) have bits 0..1 as 0; that is, we could write example (1) above as:
      mov tmp, #X
      altsb N, tmp
      setbyte value
    

    (3) If P is a pointer with a byte address in it (that is, a COG address * 4 + a byte offset within the COG register) then just do:
       altsb P, #0
       setbyte value
    

  • jmgjmg Posts: 15,148
    It has been suggested before, that the assembler be improved to allow users to write what they want

    setbyte rx2_lut_value, rx2_char, rx2_byte_index

    and then the assembler creates two lines, if required, thus eliminating all this confusion, and multiple posts.....
    ie patch opcodes are going to cause endless confusion, so they are best handled by what does the details best - your own PC
  • evanhevanh Posts: 15,192
    Go for it JMG.
  • msrobotsmsrobots Posts: 3,704
    edited 2019-02-08 10:18
    Thanks for all your input, but I am still stuck

    I tried this
    rx1_isr		rdpin	rx1_char,	rx1_pin			'get received chr
    		shr	rx1_char,	#32-8			'shift to lsb justify
    		mov	rx1_byte_index, rx1_head
    		and	rx1_byte_index, #%11			'now 0 to 3
    		mov	rx1_address,	rx1_head		'adjust to buffer start
    		shr	rx1_address,	#2
    		add	rx1_address,	rx1_lut_buff 		'by adding rx1_lut_buff
    		rdlut	rx1_lut_value,	rx1_address
    		
    		neg	rx1_byte_index				' now 0 to -3
    		add	rx1_byte_index,	#3			' now 3 to 0
    		altsb 	rx1_byte_index,	#rx1_lut_value
      		setbyte rx1_char
    
    '		cmp	rx1_byte_index,	#0		wz
    '	if_z	setbyte rx1_lut_value,	rx1_char, #3
    '		cmp	rx1_byte_index,	#1		wz
    '	if_z	setbyte rx1_lut_value,	rx1_char, #2
    '		cmp	rx1_byte_index,	#2		wz
    '	if_z	setbyte rx1_lut_value,	rx1_char, #1
    '		cmp	rx1_byte_index,	#3		wz
    '	if_z	setbyte rx1_lut_value,	rx1_char, #0
    
    		wrlut	rx1_lut_value,	rx1_address		'write byte to circular buffer in lut
    		incmod	rx1_head, 	rx1_lut_btop		'increment buffer head
    		cmp	rx1_head, 	rx1_tail 	wz	'hitting tail is bad
    	if_z	incmod	rx1_tail, 	rx1_lut_btop		'increment tail  - I am losing received chars at the end of the buffer because the buffer is full
    		reti1						'exit
    
    

    but it does not work. And I really need this 4 longs each per pair...

    I am loosing faith in being a worthy programmer,

    Mike
  • msrobots wrote: »
    Thanks for all your input, but I am still stuck

    I tried this
    rx1_isr		rdpin	rx1_char,	rx1_pin			'get received chr
    		shr	rx1_char,	#32-8			'shift to lsb justify
    		mov	rx1_byte_index, rx1_head
    		and	rx1_byte_index, #%11			'now 0 to 3
    		mov	rx1_address,	rx1_head		'adjust to buffer start
    		shr	rx1_address,	#2
    		add	rx1_address,	rx1_lut_buff 		'by adding rx1_lut_buff
    		rdlut	rx1_lut_value,	rx1_address
    		
    		neg	rx1_byte_index				' now 0 to -3
    		add	rx1_byte_index,	#3			' now 3 to 0
    		altsb 	rx1_byte_index,	#rx1_lut_value
      		setbyte rx1_char
    
    '		cmp	rx1_byte_index,	#0		wz
    '	if_z	setbyte rx1_lut_value,	rx1_char, #3
    '		cmp	rx1_byte_index,	#1		wz
    '	if_z	setbyte rx1_lut_value,	rx1_char, #2
    '		cmp	rx1_byte_index,	#2		wz
    '	if_z	setbyte rx1_lut_value,	rx1_char, #1
    '		cmp	rx1_byte_index,	#3		wz
    '	if_z	setbyte rx1_lut_value,	rx1_char, #0
    
    		wrlut	rx1_lut_value,	rx1_address		'write byte to circular buffer in lut
    		incmod	rx1_head, 	rx1_lut_btop		'increment buffer head
    		cmp	rx1_head, 	rx1_tail 	wz	'hitting tail is bad
    	if_z	incmod	rx1_tail, 	rx1_lut_btop		'increment tail  - I am losing received chars at the end of the buffer because the buffer is full
    		reti1						'exit
    
    

    but it does not work. And I really need this 4 longs each per pair...

    I am loosing faith in being a worthy programmer,

    Mike

    It's been suggested before, but I'll mention it again: Have you tried moving your code to LUT RAM and placing your buffers in COG RAM?

    It seems when this has been mentioned previously you have stated that you can't because LUT RAM is full: of buffers.

    But if the buffers are moved to COG RAM, you have that space for code, and you'll be able to pack your bytes into longs with ALTSB in COG RAM buffers.

    Please correct me if I'm off base here.
  • evanhevanh Posts: 15,192
    Mike,
    What is the content of those bytes? Doing endian reversal without a good reason is just making extra work.

    Give this a try anyway:
    rx1_isr		rdpin	rx1_char,	rx1_pin			'get received chr
    		shr	rx1_char,	#32-8			'shift to lsb justify
    
    		mov	rx1_address,	rx1_head		'adjust to buffer start
    		shr	rx1_address,	#2
    		add	rx1_address,	rx1_lut_buff 		'by adding rx1_lut_buff
    		rdlut	rx1_lut_value,	rx1_address
    
    		mov	rx1_byte_index,	rx1_head
    		and	rx1_byte_index,	#%11			'now 0 to 3
    		xor	rx1_byte_index,	#%11			'now 3 to 0
    
    		altsb 	rx1_byte_index,	#rx1_lut_value
    		setbyte	rx1_char
    
    		wrlut	rx1_lut_value,	rx1_address		'write byte to circular buffer in lut
    		incmod	rx1_head, 	rx1_lut_btop		'increment buffer head
    		cmp	rx1_head, 	rx1_tail 	wz	'hitting tail is bad
    	if_z	incmod	rx1_tail, 	rx1_lut_btop		'increment tail  - I am losing received chars at the end of the buffer because the buffer is full
    		reti1						'exit
    
  • @evanh,

    I really appreciate your help here, but after messing around with my source to figure out those misbehaviors, I finally decided to completely rewrite the driver from a new start.

    I originally started to write a one port driver and then it evolved into a two port driver since there was space left to do so, but not enough the way it is written. I have already decimal and hex output in the driver, but I really would like to add string and even dec and hex input.

    So I decided to do a clean new start, with 2 ports in there from the beginning. The good thing is that I now have a very nice test-environment to test two pairs of RX and TX.

    The good news is that indeed the smart pins in one COG work flawlessly up to sysclock baud, gapless using interrupts for RX and TX, I am still surprised about that. My echo server maxes out at one hundreds of that speed.

    But I will get there, a weekend is coming and I will have fun with the P2.

    Enjoy!

    Mike

  • evanhevanh Posts: 15,192
    edited 2019-02-08 14:26
    Mike,
    You probably don't need it now but as well as the terse instruction info in the spreadsheet there is also a section on using ALTx and ALTxx in the main doc. It's under the title of Register Indirection, just after Cog Register Layout, not far from the beginning.
  • @msrobots : Aargh! My apologies -- the code snippets we posted were theoretically correct, but didn't work with fastspin. fastspin is treating the abbreviation "setbyte x" the same as "getbyte x", which is wrong:
       getbyte x           ' should be the same as getbyte x, 0, #0
       setbyte x           ' should be the same as setbyte 0, x, #0
    
    I'll fix that in the next fastspin release. In the meantime, don't use the "setbyte x" abbreviation, use the full "setbyte 0, x, #0".
Sign In or Register to comment.