@ersmith I tried something that didn't work... Maybe there's no way it could?
@Ahle2 music code requires that you call PollTick() every so often.
I tried to jump to this function from the vga assembly driver.
Did this to have a way to get pointer to function: typedef void (*SoundOperation)(NULL);
And then this to tell vga driver the location of the function:
SoundOperation pPollTick = sound.pollTick; //RJA having video driver update music during refresh
vga.ConfigurePollTick(pPollTick);
And in the vga assembly driver, I had this:
call PollTickAddress 'update music
jmp #field 'loop
I'm sure this was wishful thinking, but is there any way to make something like that work?
@Rayman: sorry, I'm still not quite sure of the setup. Is PollTick a Spin function? And you want to call it from assembly? That's a little bit complicated, because it needs both the function address and the pointer to the object that contains PollTick. Also, of course, the Spin code expects a certain environment in the COG (some built-in functions and so on) which is not likely to be compatible with the code in a driver cog.
When taking input from terminal window with getch(), I'm seeing some interesting responses from things like keyboard arrow keys.
Just read that what you get isn't really standardized. But, is there a list somewhere of what to expect?
Looks like the arrows return two numbers, first 7 and then "D" for left, "A" for up, "C" for right, and "B" for down...
Actually, it's 27, not 7 for the first return value. Seems it also deletes the first character...
Seems a hair flaky though... Occasionally, I'm just getting the letter, without the preceding 27...
FlexProp is at the mercy of the terminal program, but most terminal programs (including I believe the default Windows one) implement ANSI escape codes for the arrow keys:
Depending on how you're reading the sequences you'll also have to be careful about timing, because the default smart pin based input has no buffer (so it's easy to lose characters). Best bet is probably to read a whole chunk of characters at once with something like read(0, buf, sizeof(buf)).
Man, getting the buffering logic right is always a brain twister when you're not expecting it.
Okay, I think I'm seeing it real now. I'm getting up to 6 characters for a single key press (with shift held)! A plain arrow key is 3 characters:
- Left: 1b 5b 44
- Right: 1b 5b 43
- Up: 1b 5b 41
- Down: 1b 5b 42
Cool, yep, I've proven an async receive smartpin can capture up to 3 adjoined characters as a single word. It does need a little massaging to extract the characters from the included framing. And amusingly, because the longest strings for a single keypress is 6 characters then it'll also handle them too, since the smartpin can buffer the second 3 character word while the first is being decoded.
I wouldn't call it a tidy solution ... but if you don't want to use interrupts or another cog, this will work.
Huh, that's unexpected, I had accidentally also configured the transmit smartpin to the same 28N1 and it worked, albeit somewhat slower. Not ideal ... fixed now.
Here's the new receiving code. The new part is the handling of the longword sized buffer, temp2. Which needs to be treated statically, allowing repeated calling inspections.
There is also a config change of the rx smartpin. The frame length parameter for WXPIN uses #27 instead of #7.
'===============================================
' input: (none)
' result: pb
'scratch: temp2
'
getch1
testb temp2, #8 wc 'framing stop-bit of prior character: high= STOP
testbn temp2, #9 andc 'framing start-bit of next character: low = START
shr temp2, #10 'shift down next character, if any
.loop1
if_nc testp #DIAGRXPIN wz 'word received in smartpin? (IN high == yes)
if_nc_and_nz jmp #.loop1 'if nothing recieved then wait
if_nc rdpin temp2, #DIAGRXPIN 'get data word from smartpin Z buffer
if_nc shr temp2, #32-28 'shift the data to bottom of register
getbyte pb, temp2, #0 'fetch character from word
ret wcz 'C/Z preserved
Sigh, the forum software is still removing tabs. Err, no, it's changed, now it stops at representing with four spaces, instead of eight. That's certainly better than deleting them. Copying the text from the edit box preserves the tabs.
PS: Here's the old code it's based on for comparison:
'===============================================
' input: (none)
' result: pb
'scratch: (none)
'
getch
testp #DIAGRXPIN wz 'byte received? (IN high == yes)
if_z rdpin pb, #DIAGRXPIN 'get data from Z buffer
if_z shr pb, #32-8 'shift the data to bottom of register
if_z ret wcz 'restore C/Z flags of calling routine
jmp #getch 'wait while Smartpin buffer is empty
PPS: The posted routine is not what I used for proving things. That code was way messier and had handling for larger strings, and timeouts to analyse and troubleshoot with.
Thanks @evanh . That looks quite intriguing. I take it temp2 isn't actually scratch, it needs to preserved across calls, and that it should be initialized to $FFFF_FFFF (or will 0 work)? I'm also a little concerned about what happens if two bytes are sent with an unusual number of bit periods between them -- it looks like the smart pin buffering will work well if bytes are sent back-to-back or at large intervals (like if the user is typing) but if the computer is streaming buffered data could things get out of sync? I hope modern computers are fast enough that there won't be any idle bits in the transmission stream.
@ersmith said:
Thanks @evanh . That looks quite intriguing. I take it temp2 isn't actually scratch, it needs to preserved across calls,
Correct.
and that it should be initialized to $FFFF_FFFF (or will 0 work)?
Either works. But not random bits.
I'm also a little concerned about what happens if two bytes are sent with an unusual number of bit periods between them -- it looks like the smart pin buffering will work well if bytes are sent back-to-back or at large intervals (like if the user is typing) but if the computer is streaming buffered data could things get out of sync? I hope modern computers are fast enough that there won't be any idle bits in the transmission stream.
Yeah, very short breaks (less than 20 bit times) will mess up. As is, it has to be contiguous or have larger breaks. It's very much targeted at key presses. Contiguous streaming will be hard pressed at higher rates but it'll certainly go faster than the old routine.
@ersmith I just noticed a difference between getch() and getchar() with regards to the enter key.
When I googled the difference, one page says getch() is non-standard. So, I guess that makes it OK.
But, it also says that getchar() is supposed to wait for the enter key. Is that right? Doesn't seem to behave that way...
In case the older versions have been replaced on Eric's website, I have many of the older versions if you can find which one you need. I'm sure it's detailed in this thread when RevA support was removed.
I also have many of the old pnut versions too.
@ersmith said:
Thanks @evanh . That looks quite intriguing. I take it temp2 isn't actually scratch, it needs to preserved across calls,
Correct.
and that it should be initialized to $FFFF_FFFF (or will 0 work)?
Either works. But not random bits.
I'm also a little concerned about what happens if two bytes are sent with an unusual number of bit periods between them -- it looks like the smart pin buffering will work well if bytes are sent back-to-back or at large intervals (like if the user is typing) but if the computer is streaming buffered data could things get out of sync? I hope modern computers are fast enough that there won't be any idle bits in the transmission stream.
Yeah, very short breaks (less than 20 bit times) will mess up. As is, it has to be contiguous or have larger breaks. It's very much targeted at key presses. Contiguous streaming will be hard pressed at higher rates but it'll certainly go faster than the old routine.
@evanh I like this solution with a small buffer for avoiding missed keyboard presses etc, I wonder if there is a good way to handle the other short break times by hunting for start bits in the residual word. Maybe you could invert (NOT), reverse (REV) and encode (ENCOD) the residual to find the next start bit position and then shift appropriately for the next character. If/when the data wraps 32 bit boundaries however things might get messy.
Yeah, I thought about that but buried my head from it. I might have a nosey after I'm done with the fill functions. EDIT: I fear it'll lead to interrupts and large buffering.
There's another problem. I've just realised that how I used the old routine often relied on checking for hardware buffer full before calling it. Surprisingly, if no more than three characters for a key press then it'll be just as good, that covers the arrow keys nicely. But for the longer six character strings, the servicing response has to be quick. In this case a lower baud would provide more time.
In either case the old programs have to also be smartened up to empty the soft buffer. Not sure yet how best to do it ...
It might be possible to simply detect and report that there is more data available and notify the caller that there is more data pending when you return a character, so it can continue empty as much as possible each time in a loop and keep it as empty as much as possible. Of course that still depends on the application to do this work and probably also buffer elsewhere.
@TonyB_ said:
Does FlexSpin still l support rev.A? If so, can I tell it to generate errors if rev.B instructions are used?
Yep, use flexspin -2a Err, no it doesn't support that option any longer.
@Cluso99 said:
In case the older versions have been replaced on Eric's website, I have many of the older versions if you can find which one you need. I'm sure it's detailed in this thread when RevA support was removed.
I also have many of the old pnut versions too.
I've searched this thread and FlexProp v5.0.2 should support the rev.A. I have no idea what last version of PNut works. Did Spin2 ever work with rev.A?
This is all so I can donate my rev.A Eval board to a friend.
@TonyB_ said:
Does FlexSpin still l support rev.A?
Not officially, but I haven't removed the rev A code, so it may still work (the command line option is "-2a"), I think someone on the forums reported success with it a few weeks ago. You're on your own though if things don't work .
@Rayman said:
@ersmith I just noticed a difference between getch() and getchar() with regards to the enter key.
When I googled the difference, one page says getch() is non-standard. So, I guess that makes it OK.
But, it also says that getchar() is supposed to wait for the enter key. Is that right? Doesn't seem to behave that way...
Your google results are talking about the default behavior of getchar() on many platforms. But I don't think the C standard requires getchar() to wait for enter. For example on Linux you can put the terminal into raw mode and then getchar() should return as soon as any character it typed. flexprop on P2 is pretty similar to that.
@TonyB_ said:
I've searched this thread and FlexProp v5.0.2 should support the rev.A. I have no idea what last version of PNut works. Did Spin2 ever work with rev.A?
Pnut never mixed them. Pre-v33 was revA. v33 onwards is revB/C. Needless to say Chip's Spin2 interpreter never supported revA.
I've attached a repackaged zip of the final v32j files. The original download contained a lot of FPGA bin files that made it 21 MB. I've stripped all those out.
Comments
@ersmith I tried something that didn't work... Maybe there's no way it could?
@Ahle2 music code requires that you call PollTick() every so often.
I tried to jump to this function from the vga assembly driver.
Did this to have a way to get pointer to function:
typedef void (*SoundOperation)(NULL);
And then this to tell vga driver the location of the function:
And in the vga assembly driver, I had this:
I'm sure this was wishful thinking, but is there any way to make something like that work?
@Rayman: sorry, I'm still not quite sure of the setup. Is PollTick a Spin function? And you want to call it from assembly? That's a little bit complicated, because it needs both the function address and the pointer to the object that contains PollTick. Also, of course, the Spin code expects a certain environment in the COG (some built-in functions and so on) which is not likely to be compatible with the code in a driver cog.
@ersmith Thanks, that's what I figured...
I can I do packed structures in c?
Mike
No, FlexC doesn't support packed structures yet.
When taking input from terminal window with getch(), I'm seeing some interesting responses from things like keyboard arrow keys.
Just read that what you get isn't really standardized. But, is there a list somewhere of what to expect?
Looks like the arrows return two numbers, first 7 and then "D" for left, "A" for up, "C" for right, and "B" for down...
Actually, it's 27, not 7 for the first return value. Seems it also deletes the first character...
Seems a hair flaky though... Occasionally, I'm just getting the letter, without the preceding 27...
@Rayman ,
Looks like we're going to need a termcap file and program.
Mike
FlexProp is at the mercy of the terminal program, but most terminal programs (including I believe the default Windows one) implement ANSI escape codes for the arrow keys:
https://en.wikipedia.org/wiki/ANSI_escape_code#Terminal_input_sequences
Depending on how you're reading the sequences you'll also have to be careful about timing, because the default smart pin based input has no buffer (so it's easy to lose characters). Best bet is probably to read a whole chunk of characters at once with something like read(0, buf, sizeof(buf)).
Ok, makes sense now.
Guess this means one can’t reliably use the arrows and function keys, etc.
/me ponders what results a smartpin with 18N1 receive framing config would produce ...
Oh, it's more than two characters for some keys ...
Man, getting the buffering logic right is always a brain twister when you're not expecting it.
Okay, I think I'm seeing it real now. I'm getting up to 6 characters for a single key press (with shift held)! A plain arrow key is 3 characters:
- Left: 1b 5b 44
- Right: 1b 5b 43
- Up: 1b 5b 41
- Down: 1b 5b 42
Cool, yep, I've proven an async receive smartpin can capture up to 3 adjoined characters as a single word. It does need a little massaging to extract the characters from the included framing. And amusingly, because the longest strings for a single keypress is 6 characters then it'll also handle them too, since the smartpin can buffer the second 3 character word while the first is being decoded.
I wouldn't call it a tidy solution ... but if you don't want to use interrupts or another cog, this will work.
Huh, that's unexpected, I had accidentally also configured the transmit smartpin to the same 28N1 and it worked, albeit somewhat slower. Not ideal ... fixed now.
Here's the new receiving code. The new part is the handling of the longword sized buffer, temp2. Which needs to be treated statically, allowing repeated calling inspections.
There is also a config change of the rx smartpin. The frame length parameter for WXPIN uses #27 instead of #7.
Sigh, the forum software is still removing tabs. Err, no, it's changed, now it stops at representing with four spaces, instead of eight. That's certainly better than deleting them. Copying the text from the edit box preserves the tabs.
PS: Here's the old code it's based on for comparison:
PPS: The posted routine is not what I used for proving things. That code was way messier and had handling for larger strings, and timeouts to analyse and troubleshoot with.
Thanks @evanh . That looks quite intriguing. I take it temp2 isn't actually scratch, it needs to preserved across calls, and that it should be initialized to $FFFF_FFFF (or will 0 work)? I'm also a little concerned about what happens if two bytes are sent with an unusual number of bit periods between them -- it looks like the smart pin buffering will work well if bytes are sent back-to-back or at large intervals (like if the user is typing) but if the computer is streaming buffered data could things get out of sync? I hope modern computers are fast enough that there won't be any idle bits in the transmission stream.
Correct.
Either works. But not random bits.
Yeah, very short breaks (less than 20 bit times) will mess up. As is, it has to be contiguous or have larger breaks. It's very much targeted at key presses. Contiguous streaming will be hard pressed at higher rates but it'll certainly go faster than the old routine.
Hehe, yes, it's does count on the transmitter having good hardware buffers and/or not getting waylaid part way through.
Does FlexSpin still l support rev.A? If so, can I tell it to generate errors if rev.B instructions are used?
@ersmith I just noticed a difference between getch() and getchar() with regards to the enter key.
When I googled the difference, one page says getch() is non-standard. So, I guess that makes it OK.
But, it also says that getchar() is supposed to wait for the enter key. Is that right? Doesn't seem to behave that way...
Yep, use flexspin -2a Err, no it doesn't support that option any longer.
In case the older versions have been replaced on Eric's website, I have many of the older versions if you can find which one you need. I'm sure it's detailed in this thread when RevA support was removed.
I also have many of the old pnut versions too.
@evanh I like this solution with a small buffer for avoiding missed keyboard presses etc, I wonder if there is a good way to handle the other short break times by hunting for start bits in the residual word. Maybe you could invert (NOT), reverse (REV) and encode (ENCOD) the residual to find the next start bit position and then shift appropriately for the next character. If/when the data wraps 32 bit boundaries however things might get messy.
Yeah, I thought about that but buried my head from it. I might have a nosey after I'm done with the fill functions. EDIT: I fear it'll lead to interrupts and large buffering.
There's another problem. I've just realised that how I used the old routine often relied on checking for hardware buffer full before calling it. Surprisingly, if no more than three characters for a key press then it'll be just as good, that covers the arrow keys nicely. But for the longer six character strings, the servicing response has to be quick. In this case a lower baud would provide more time.
In either case the old programs have to also be smartened up to empty the soft buffer. Not sure yet how best to do it ...
It might be possible to simply detect and report that there is more data available and notify the caller that there is more data pending when you return a character, so it can continue empty as much as possible each time in a loop and keep it as empty as much as possible. Of course that still depends on the application to do this work and probably also buffer elsewhere.
I've searched this thread and FlexProp v5.0.2 should support the rev.A. I have no idea what last version of PNut works. Did Spin2 ever work with rev.A?
This is all so I can donate my rev.A Eval board to a friend.
Not officially, but I haven't removed the rev A code, so it may still work (the command line option is "-2a"), I think someone on the forums reported success with it a few weeks ago. You're on your own though if things don't work .
Your google results are talking about the default behavior of getchar() on many platforms. But I don't think the C standard requires getchar() to wait for enter. For example on Linux you can put the terminal into raw mode and then getchar() should return as soon as any character it typed. flexprop on P2 is pretty similar to that.
Pnut never mixed them. Pre-v33 was revA. v33 onwards is revB/C. Needless to say Chip's Spin2 interpreter never supported revA.
I've attached a repackaged zip of the final v32j files. The original download contained a lot of FPGA bin files that made it 21 MB. I've stripped all those out.
EDIT: Corrected from v31 to v32j