You don't need a COGSTOP command to stop a cog. The SPIN interpreter, when it calls the main method (routine) of the program, puts a return address on the stack which points to a COGSTOP that stops the current cog (thereby resetting the direction register and the counter control register).
A cog runs a single execution thread. Unless you write them specifically to multitask, you can't do more than one thing in a cog. The FullDuplexSerial object for example combines a transmit thread and a receive thread in the same cog, but they're written to alternate functions back and forth. You could use the same cog for Synth and one soft UART because the UART doesn't use the counters and Synth doesn't need to do anything once the counters are initialized (unless you want to change the frequency). The TV_Terminal object uses a cog for the video generation and needs the counters in the cog for that as well.
Couldn't synchronous serial achieve higher throughput rates for this application than asynchronous?
Of course, you'd have to roll your own code, but I think it could work something like this:
(Note that CLOCK here does not refer to the 5MHz Propeller clock)
Master: Puts bit on DATA
Master: Brings CLOCK low
Master: waitpne for ACK to change state
Slave: Reads data bit
Slave: Toggles ACK
Slave: waitpne for CLOCK to change state
Master: Puts next bit on DATA
Master: Toggles CLOCK
Master: waitpne for ACK
Slave: Reads data bit
Slave: Toggles ACK
Slave: waitpne for CLOCK to change state
... and so on, and ends with Master bringing CLOCK high again so that the slave cog can wait for it to go low for the next byte.
This could go as fast as the two processors could handle it, with 1 bit being sent with every change of state of the CLOCK signal (i.e. the bits per second would be twice as fast as the clock rate). Since it is not asynchronous, you wouldn't have to have any "timing margins" like you would have to have for I2C or RS-232 asynchronous serial. The time it takes each Propeller to fetch/store each bit should give plenty of time for the other Propeller to set up it's waitpne to catch the next clock or acknowledge signal.
As for the slave possibly halting the master indefinitely one could either A) Hope it never happens, or have a watchdog program on another cog check to make sure the communication cog is not hung up, and reset it if it is. This wouldn't tie up the watchdog cog exclusively; it could run other code most of the time and just check every few milliseconds.
Dennis,
Thanks, I'll keep this in mind if I need more speed. Right now, for some reason I cannot get the FullDuplexSerial going.
Mike,
I've commented out some objects, so only have the display and 1 soft uart going, I think. Display works fine; never had a problem with that. But am pulling out hair trying to debug why the uart isn't working right.
With just this:
repeat
if (c := PICSer.rxcheck) <> -1
c := rxbyte ' get rx byte
Display.hex(c,2) ' display in hex
Display.str(string(" <= GOT HERE!")) ' if get here, show it
OUTA[noparse][[/noparse]16] := INA ' drive LED on 16 to state on uart input
I'm looking to have the uart receive a byte, display it, and also 'scream' that I got there. Nada.
In PUB, there is a cognew(Control1,@stack), then a waitcnt(.....), and PICSer.start(PIC_Tx, PIC_Rx, %0000, PIC_Baud), then come first PRI. I've commented out the second uart and Synth temporarily; want to get a single uart going first.
I'm wondering if there are other 'hooks' to picking up a receive byte? A PIC (no MAXnnnn parts involved) through a resistor driving the Prop uart input. That last line lets me scope that the uart input pin is working right; though the loop is too slow to properly sample at 38400 baud signalling; doesn't pick up a single 1 bit, or if does stretches it out, but lets me know pin 5 is receiving a signal. Cheap debugger.
I've tried inverting the Rx via the mode bits; didn't help. Seems I should at least see some garbage coming through if the baudrates were off.
Found, if I moved the PICSer.start(.......) in PRI, I was getting the 'GOT HERE!' running all over the screen (scrolling up). Even that was sort of encouraging, though not right, as the uart wasn't receiving anything.
Moved the Synth from after PUB into PRI and now have the 5 MHz desired clock going out on A24.
Another of those 'lightbulb' moments in the shower.
Now, if I could have another for FullDuplexSerial.
I tried a number of things. Possibly I'm getting closer.
Find if I place the 'PICSer.start(......)' where it is, I get something on the screen. Except it is displaying '00...' over and over. Without sending the usart a byte. If I place it just before or after the PRI, then nothing happens uart-wise, but at least I can scope the LED signal on A16; that is it doesn't block the last line from working.
PUB Main
PICSer.start(PIC_Tx, PIC_Rx, %0000, PIC_Baud)
cognew(Control1,@stack)
waitcnt(clkfreq >> 4 + cnt)
repeat until status == StatusIdle
PRI Control1 | i,r,k,keyok
Fsynth.synth("A", 24, 5_000_000)
status := StatusInit 'set system status to Initialize
Display.start(12)
Display.setcolors(@tv_palette)
gotoxy(CenterAlign(@title),0)
Display.str(@title)
waitcnt(clkfreq << 1 + cnt) 'wait 2 seconds
DisplayHelpScreen 'start in help screen
DIRA~ ' needed if 'OUTA[noparse][[/noparse]16] := INA' used below
DIRA[noparse][[/noparse]16]~~ ' to drive LED to see line level
' repeat
' OUTA[noparse][[/noparse]16] := INA
repeat
' if (c := PropSer.rxcheck) <> -1
' process a byte from the other Propeller
if (c := PICSer.rxcheck) <> -1
' process a byte from PICSer
rxcheck := -1
c := PICSer.rx
Display.hex(c,2)
Display.str(string("..."))
' Display.str(string(" <= GOT HERE! ")) 'display
OUTA[noparse][[/noparse]16] := INA
I've read the COGNEW section, looked at numerous listings, but must not be catching on to what it takes to work.
I want one uart to run in its separate COG, the second in its own, and can probably run all the rest, the Main, in its own.
1) Why do you do the "rxcheck := -1"? It doesn't seem to be needed for anything. PICSer.rxcheck simply looks to see if there's anything placed in the receive buffer for PICSer. If so, it returns the character. If not, it returns -1. If it returns the character, that character is removed from the buffer. Your later call "c := PICSer.rx" waits for the next character to be received (and will wait until it's there). That probably is not what you want.
2) Why do you need the separate cog for Control1? Are you planning on making it more complicated? Right now it just starts a few things, then basically hangs
1. Got that from someone, don't now recall who. Sounds like all that needs be done is check 'c' if -1 or a valid code. Or is that totallly wrong?
2. Control1 will be much more involved, probably pages of code. And there might even be several more cogs involved, as I presently understand things Spin-wise.
Yes, it will essentially be awaiting input from one of two UARTs. Then process the commands or data. Some commands will involve the second UART which has to interface to another board. .
Harley,
1) Yes, just check (c := PICSer.rxcheck) for a value <> -1. If not, then it's the character you hoped for.
2) Keep in mind that the soft UARTs do have buffers that can hold up to 16 bytes each. That gives you some leeway in processing the data from the other Propeller and the PIC if you want to do that all in one cog.
Mike
Thanks Mike,
......for all the help and suggestions.
Hopefully I'll soon tackle this problem, what ever it is, and I'll be on my way to work off other obstacles.
Have a good weekend, what's left of it. Again thanks. This Spin language is sure powerful, but somewhat of a change in thinking from previous micros (last few years were into PICs).
Went back to the program and accidently saw something I'd not noticed before. Couldn't believe it; had the tx and rx pins switched in the .start statement.
Works now. Phew! One problem, I get an 'FF' after the received byte is displayed. Not sure why that happens; but the GOOD NEWS is each incoming byte value is displayed. (For now I can filter out any 'FF' value)
Harley,
If the I/O line from the PIC is kept low after the last bit of the character is transmitted, it will act as an extra start bit for a second character with all the data bits as ones (high). In asynchronous I/O, there is a start bit (a low pulse) followed by 8 pulse times, followed by a stop bit (a high pulse) after which the I/O line should remain high until the next start bit. That may not be happening and the serial I/O routines see that as an extra character of $FF.
Mike
Mike said...
Harley,
What you posted should work (also just saying "PICSer.tx(c)" should work). There must be something else you're doing that's interfering.
Mike
Thanks for the 'simplification'; rather than two lines. I've tried various things but haven't yet found what won't let it work.
Measure 3.29v on the 3.3v pin, and 3.28v on the 'tx' pin with a resistor to the PIC uart input. My tx pin just sits solidly at the HI state!?
Time for lots more digging and 'head scratching'...
Harley,
Whatever's going on probably has to do with your program, maybe the initialization is off, maybe you're somehow trying to access the serial lines from another cog (FullDuplexSerial takes care of initializing the serial pins itself).
Mike
Mike said...
Harley,
Whatever's going on probably has to do with your program, maybe the initialization is off, maybe you're somehow trying to access the serial lines from another cog (FullDuplexSerial takes care of initializing the serial pins itself).
Mike
Thanks for 'hitting me over the head' with the 'initializing' comment. Went back over the listing AGAIN. When I got to the second uart init, found it was setting up the same pins; probably had them switched way back in time, commented out the second to isolate things. Yesterday when I un-commented it, I had two soft uarts fighting for the same pins, and the second was init'ed last (if that has anything to do with it).
Anyway, the program works correctly now. Amazing how easy it is to mess up, yet so difficult to find a bug when 'too close' to it. Fortunately I'm using TV_text for sort of a debugger; looking at all the 'registers' I'm using. The board with the PIC has 28 keys and some 7-segment LEDs. Monitoring input keypress, and registers the value should go to, and the modes that get set up, is simplified with this Poor Man's Debugger.
I'm wanting to move nibbles, one at a time, from one variable to another. But it appears the 'range' syntax '..' is only for CASE and I/Os (DIR, OUT, IN).
I wrote the following, but find the compiler balks; gives me a 'Expected "]"' error after the first number:
reg1[noparse][[/noparse]3..0] := reg2[noparse][[/noparse]15..12] ' as an example
Is there a clean way to move/select portions of a 32-bit value?___
I've look at a number of listing, but don't recognize any procedure for this.
Little more complicated than what I'd hoped for. Not sure why the '..' range couldn't be used for other things.
Ok, so it's the Shift, Mask, Or task for these operations. I'm just getting into some of these 'trickier' issues. Learning curves are SO MUCH FUN, huh?
Nice to have 'one liners' though. Thanks again. Boy, this sure is fun stuff.
I am using FullDuplexSerial. No problem using it except....
1. The receiving board has some processing for each byte received. What would be the best way to know when the succeeding bytes are to be sent. Some sort of delay is in order at the transmitting side, the Prop.
It seems there was some relatively simple example on the forum, a one or two liner, that handles such a need. Does anyone recall such code?__
2. Since there is no interrupt on the Prop, how would one generate a background 'timer', say 1 to 15 or so seconds, that would post a flag when the time interval is up?____ I'd guess it takes another cog to do so (presently have some free cogs). Is there a good reference to cog-to-cog signalling?___ It isn't critical how soon the 'time up' flag is honored, as some other task(s) may be running.
Using TV_text as a debug window has been highly helpful in monitoring of my developing code. Monitoring some 1/2 dozen variables makes for quicker results.
Harley,
The assembly language would have to be modified to properly add some delay. You would like that to be configurable. The issue is that you can tell when the transmit buffer is empty from the SPIN code, but you don't know when the character has finished being transmitted. Basically, you want to add additional stop bits to allow the receiver to process the information.
The assembly language could also be modified to signal that the last byte has been transmitted and your code could just wait for that signal, then wait for whatever interval you want (with a WAITCNT) before putting another character in the buffer.
Other options include just using the receive routine in FullDuplexSerial and using a SPIN routine for transmitting, then waiting after each character is sent.
It seems possible, but am not sure how to test this, to be able to write to OUTA register while those pins are in an input state. What I'm aiming for is to make a 'tri-state' port.
Then when a 'select' signal is tested via WAITPEQ or WAITPNE then quickly do a DIRA (probably MOVD?) and output to an external bus. When select signal goes to other state, then make the pins inputs again.
In assembly this would 5 + 4 = 9 clock times; at 80 MHz, for 112.5 nsec to output to bus. Would like it much shorter, really. Is there any 'tricks' to do it faster?___
Comments
A cog runs a single execution thread. Unless you write them specifically to multitask, you can't do more than one thing in a cog. The FullDuplexSerial object for example combines a transmit thread and a receive thread in the same cog, but they're written to alternate functions back and forth. You could use the same cog for Synth and one soft UART because the UART doesn't use the counters and Synth doesn't need to do anything once the counters are initialized (unless you want to change the frequency). The TV_Terminal object uses a cog for the video generation and needs the counters in the cog for that as well.
Of course, you'd have to roll your own code, but I think it could work something like this:
(Note that CLOCK here does not refer to the 5MHz Propeller clock)
Master: Puts bit on DATA
Master: Brings CLOCK low
Master: waitpne for ACK to change state
Slave: Reads data bit
Slave: Toggles ACK
Slave: waitpne for CLOCK to change state
Master: Puts next bit on DATA
Master: Toggles CLOCK
Master: waitpne for ACK
Slave: Reads data bit
Slave: Toggles ACK
Slave: waitpne for CLOCK to change state
... and so on, and ends with Master bringing CLOCK high again so that the slave cog can wait for it to go low for the next byte.
This could go as fast as the two processors could handle it, with 1 bit being sent with every change of state of the CLOCK signal (i.e. the bits per second would be twice as fast as the clock rate). Since it is not asynchronous, you wouldn't have to have any "timing margins" like you would have to have for I2C or RS-232 asynchronous serial. The time it takes each Propeller to fetch/store each bit should give plenty of time for the other Propeller to set up it's waitpne to catch the next clock or acknowledge signal.
As for the slave possibly halting the master indefinitely one could either A) Hope it never happens, or have a watchdog program on another cog check to make sure the communication cog is not hung up, and reset it if it is. This wouldn't tie up the watchdog cog exclusively; it could run other code most of the time and just check every few milliseconds.
Thanks, I'll keep this in mind if I need more speed. Right now, for some reason I cannot get the FullDuplexSerial going.
Mike,
I've commented out some objects, so only have the display and 1 soft uart going, I think. Display works fine; never had a problem with that. But am pulling out hair trying to debug why the uart isn't working right.
With just this:
I'm looking to have the uart receive a byte, display it, and also 'scream' that I got there. Nada.
In PUB, there is a cognew(Control1,@stack), then a waitcnt(.....), and PICSer.start(PIC_Tx, PIC_Rx, %0000, PIC_Baud), then come first PRI. I've commented out the second uart and Synth temporarily; want to get a single uart going first.
I'm wondering if there are other 'hooks' to picking up a receive byte? A PIC (no MAXnnnn parts involved) through a resistor driving the Prop uart input. That last line lets me scope that the uart input pin is working right; though the loop is too slow to properly sample at 38400 baud signalling; doesn't pick up a single 1 bit, or if does stretches it out, but lets me know pin 5 is receiving a signal. Cheap debugger.
I've tried inverting the Rx via the mode bits; didn't help. Seems I should at least see some garbage coming through if the baudrates were off.
Found, if I moved the PICSer.start(.......) in PRI, I was getting the 'GOT HERE!' running all over the screen (scrolling up). Even that was sort of encouraging, though not right, as the uart wasn't receiving anything.
Any suggestions to accessing FullDuplexSerial?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Harley Shanko
h.a.s. designn
Another of those 'lightbulb' moments in the shower.
Now, if I could have another for FullDuplexSerial.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Harley Shanko
h.a.s. designn
What's "c := rxbyte"? To read from PICSer, you need a "c := PICSer.rx".
I tried a number of things. Possibly I'm getting closer.
Find if I place the 'PICSer.start(......)' where it is, I get something on the screen. Except it is displaying '00...' over and over. Without sending the usart a byte. If I place it just before or after the PRI, then nothing happens uart-wise, but at least I can scope the LED signal on A16; that is it doesn't block the last line from working.
I've read the COGNEW section, looked at numerous listings, but must not be catching on to what it takes to work.
I want one uart to run in its separate COG, the second in its own, and can probably run all the rest, the Main, in its own.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Harley Shanko
h.a.s. designn
1) Why do you do the "rxcheck := -1"? It doesn't seem to be needed for anything. PICSer.rxcheck simply looks to see if there's anything placed in the receive buffer for PICSer. If so, it returns the character. If not, it returns -1. If it returns the character, that character is removed from the buffer. Your later call "c := PICSer.rx" waits for the next character to be received (and will wait until it's there). That probably is not what you want.
2) Why do you need the separate cog for Control1? Are you planning on making it more complicated? Right now it just starts a few things, then basically hangs
1. Got that from someone, don't now recall who. Sounds like all that needs be done is check 'c' if -1 or a valid code. Or is that totallly wrong?
2. Control1 will be much more involved, probably pages of code. And there might even be several more cogs involved, as I presently understand things Spin-wise.
Yes, it will essentially be awaiting input from one of two UARTs. Then process the commands or data. Some commands will involve the second UART which has to interface to another board. .
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Harley Shanko
h.a.s. designn
1) Yes, just check (c := PICSer.rxcheck) for a value <> -1. If not, then it's the character you hoped for.
2) Keep in mind that the soft UARTs do have buffers that can hold up to 16 bytes each. That gives you some leeway in processing the data from the other Propeller and the PIC if you want to do that all in one cog.
Mike
......for all the help and suggestions.
Hopefully I'll soon tackle this problem, what ever it is, and I'll be on my way to work off other obstacles.
Have a good weekend, what's left of it. Again thanks. This Spin language is sure powerful, but somewhat of a change in thinking from previous micros (last few years were into PICs).
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Harley Shanko
h.a.s. designn
Went back to the program and accidently saw something I'd not noticed before. Couldn't believe it; had the tx and rx pins switched in the .start statement.
Works now. Phew! One problem, I get an 'FF' after the received byte is displayed. Not sure why that happens; but the GOOD NEWS is each incoming byte value is displayed. (For now I can filter out any 'FF' value)
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Harley Shanko
h.a.s. designn
If the I/O line from the PIC is kept low after the last bit of the character is transmitted, it will act as an extra start bit for a second character with all the data bits as ones (high). In asynchronous I/O, there is a start bit (a low pulse) followed by 8 pulse times, followed by a stop bit (a high pulse) after which the I/O line should remain high until the next start bit. That may not be happening and the serial I/O routines see that as an extra character of $FF.
Mike
I'm using FullDuplexSerial. But it doesn't transmit.
Is there more than this fragment required to tranmit a byte?___ The receive side runs OK.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Harley Shanko
h.a.s. designn
What you posted should work (also just saying "PICSer.tx(c)" should work). There must be something else you're doing that's interfering.
Mike
Thanks for the 'simplification'; rather than two lines. I've tried various things but haven't yet found what won't let it work.
Measure 3.29v on the 3.3v pin, and 3.28v on the 'tx' pin with a resistor to the PIC uart input. My tx pin just sits solidly at the HI state!?
Time for lots more digging and 'head scratching'...
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Harley Shanko
h.a.s. designn
Whatever's going on probably has to do with your program, maybe the initialization is off, maybe you're somehow trying to access the serial lines from another cog (FullDuplexSerial takes care of initializing the serial pins itself).
Mike
Thanks for 'hitting me over the head' with the 'initializing' comment. Went back over the listing AGAIN. When I got to the second uart init, found it was setting up the same pins; probably had them switched way back in time, commented out the second to isolate things. Yesterday when I un-commented it, I had two soft uarts fighting for the same pins, and the second was init'ed last (if that has anything to do with it).
Anyway, the program works correctly now. Amazing how easy it is to mess up, yet so difficult to find a bug when 'too close' to it. Fortunately I'm using TV_text for sort of a debugger; looking at all the 'registers' I'm using. The board with the PIC has 28 keys and some 7-segment LEDs. Monitoring input keypress, and registers the value should go to, and the modes that get set up, is simplified with this Poor Man's Debugger.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Harley Shanko
h.a.s. designn
I wrote the following, but find the compiler balks; gives me a 'Expected "]"' error after the first number:
Is there a clean way to move/select portions of a 32-bit value?___
I've look at a number of listing, but don't recognize any procedure for this.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Harley Shanko
h.a.s. designn
You've got to do shifting, masking, or's, etc. Your example would be:
Little more complicated than what I'd hoped for. Not sure why the '..' range couldn't be used for other things.
Ok, so it's the Shift, Mask, Or task for these operations. I'm just getting into some of these 'trickier' issues. Learning curves are SO MUCH FUN, huh?
Nice to have 'one liners' though. Thanks again. Boy, this sure is fun stuff.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Harley Shanko
h.a.s. designn
1. The receiving board has some processing for each byte received. What would be the best way to know when the succeeding bytes are to be sent. Some sort of delay is in order at the transmitting side, the Prop.
It seems there was some relatively simple example on the forum, a one or two liner, that handles such a need. Does anyone recall such code?__
2. Since there is no interrupt on the Prop, how would one generate a background 'timer', say 1 to 15 or so seconds, that would post a flag when the time interval is up?____ I'd guess it takes another cog to do so (presently have some free cogs). Is there a good reference to cog-to-cog signalling?___ It isn't critical how soon the 'time up' flag is honored, as some other task(s) may be running.
Using TV_text as a debug window has been highly helpful in monitoring of my developing code. Monitoring some 1/2 dozen variables makes for quicker results.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Harley Shanko
h.a.s. designn
The assembly language would have to be modified to properly add some delay. You would like that to be configurable. The issue is that you can tell when the transmit buffer is empty from the SPIN code, but you don't know when the character has finished being transmitted. Basically, you want to add additional stop bits to allow the receiver to process the information.
The assembly language could also be modified to signal that the last byte has been transmitted and your code could just wait for that signal, then wait for whatever interval you want (with a WAITCNT) before putting another character in the buffer.
Other options include just using the receive routine in FullDuplexSerial and using a SPIN routine for transmitting, then waiting after each character is sent.
It seems possible, but am not sure how to test this, to be able to write to OUTA register while those pins are in an input state. What I'm aiming for is to make a 'tri-state' port.
Then when a 'select' signal is tested via WAITPEQ or WAITPNE then quickly do a DIRA (probably MOVD?) and output to an external bus. When select signal goes to other state, then make the pins inputs again.
In assembly this would 5 + 4 = 9 clock times; at 80 MHz, for 112.5 nsec to output to bus. Would like it much shorter, really. Is there any 'tricks' to do it faster?___
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Harley Shanko
h.a.s. designn