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.
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.
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:
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.
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?
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.
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.
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...
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
- 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
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.
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:
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
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
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.
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".
Comments
yes, exactly.
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
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
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.
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.
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: 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:
(Edited to fix a misunderstanding on my part.)
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
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
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.
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
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
with something shorter
Mike
I suspect ALTI can help with SETBYTE, I've not looked into that instruction yet.
So ALTSB isn't too broken? Seem to be going round in loops here, and I haven't helped!
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
(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: 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:
(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:
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
I tried this
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.
What is the content of those bytes? Doing endian reversal without a good reason is just making extra work.
Give this a try anyway:
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
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.