I was also thinking that limiting the glossary to high level definitions might be a good place to start, since newbies aren't going to be delving down too far into the dictionary as they learn and write code.
<snip>
I'm unclear how multiple cogs are set up with stack space and copying the task registers. Seeing how it's done for something simple like the LED question I posed, will help me apply it to my situation.
Yes agreed that we mainly concentrate on the higher level words but EMIT was included because it is revectorable.
As regards to stack space you only need to set this up for anything that goes beyond the 4 level cog stack space. If the pointer isn't set then it won't try to access hub memory. However you have seen examples already and it is simply a matter of allocating some memory, perhaps using LONGS and seting the stack pointer during the startup of a task with SP! thus:
8 LONGS mystk
: MYTASK mystk SP! <and the rest> ;
Any task or cog that talks to streaming I/O such as the serial console sometimes needs to have its own I/O vectors since it may revector the EMIT to talk to the VGA screen for instance. The solution would be to have a copy of these vectors for all cogs but the trouble is that whenever you input or output you need to print numbers perhaps which converts numbers to strings before printing the string. So these cogs need to have their own copy that the Forth primitives such as KEY EMIT PRINT GETWORD and their variants use that doesn't involve anything time consuming and complex to implement.
A simple internal opcode called REG accepts an 8-bit offset from a base register as a quick and simple way to access local hub variables such as mentioned. This cuts down the need to specify a 16-bit address and while it makes the code more compact it also allows each cog to change the address stored in that base address register to use a different set of hub variables.
Now the order of the hub variables are arranged in such a way that rather than having to allocate 256 bytes of memory for another cog you only need 128 bytes since memory is limited. So therefore this is what you do to change it.
128 BYTES myregs --- allocate space for task registers (local variables)
: MYTASK
mystk SP!
myregs 7 COGREG! --- set REG base address of this cog to point to new set
<and the rest>
;
But none of those "new" registers in myregs will be initialized, they will all be zero so it is prudent to preset them by making a copy of the console cog's (cog 0) registers like this:
$24 myregs 128 CMOVE
This operation BTW can be performed during compile time without any side effects or included in your task's startup either way. The $24 is the default address of cog0's task registers and although they could be changed there isn't any reason to do so.
All this documentation makes me feel lost in space, oh the pain, the pain.
Tachyon is an absolutely amazing achievement Peter!
I read up a bit on Forth on my recent flight. I didn't like it because it is the reverse of the way I think, and have been thinking for the last 40+ years, about code flow. That's my loss because I just cannot getup the motivation to use Tachyon. However, for you younger minds that haven't been corrupted like mine, jump right on in.
Just love the pics you are getting from SPLAT. I am going to need to look at this part as I am sure I could use it.
Tachyon is an absolutely amazing achievement Peter!
I read up a bit on Forth on my recent flight. I didn't like it because it is the reverse of the way I think, and have been thinking for the last 40+ years, about code flow. That's my loss because I just cannot getup the motivation to use Tachyon. However, for you younger minds that haven't been corrupted like mine, jump right on in.
Just love the pics you are getting from SPLAT. I am going to need to look at this part as I am sure I could use it.
come on - join the fun
would be great to have you on board
even with arguments first and then the function name
this is nothing compared to a language that does not use western characters ;-)
it's still just a programming language
With my 7219 display module having taken a dive, I'd like to put a TFT display to work in it's place and perhaps display additional data. Where can I find info on using TV-text output (3-pin, just how it's done in SPIN) in Tachyon?
With my 7219 display module having taken a dive, I'd like to put a TFT display to work in it's place and perhaps display additional data. Where can I find info on using TV-text output (3-pin, just how it's done in SPIN) in Tachyon?
There should be no reason why you couldn't use the VGA that's built in. Although it is a basic 32x15 character display I also have line graphics and big digit modes in a variety of font sizes. i think it would be perfect for what you want.
There is one rather large reason I can't use VGA in this instance: The TFT color monitor I have is 7" and the VGA monitor I have is 28", which is too large to fit on my shelf. The TFT monitor uses an RCA plug which (under SPIN) functioned just fine with a 3-pin TV output.
There is one rather large reason I can't use VGA in this instance: The TFT color monitor I have is 7" and the VGA monitor I have is 28", which is too large to fit on my shelf. The TFT monitor uses an RCA plug which (under SPIN) functioned just fine with a 3-pin TV output.
Is this functionality not available in Tachyon?
I suppose if I were doing a full professional package I might try to include a lot more stuff but I've only just had time to fire up my DE2-115 for the new P2 and try some code. Somehow I don't think I might get around to integrating this although it is very similar in a lot of ways to the VGA driver. I want to fire up a version of Tachyon on the P2 now (in addition to my XMC1100 ARM parts).
Thanks, Peter.
I guess the short answer to my question is "no", which I can certainly understand, given what you are in the midst of! I would then ask if there is a means to incorporate the spin code, that provides this functionality, into a Tachyon program? I'm thinking of perhaps loading the spin code so it runs in a separate cog and has a 'hook' available to be used from Tachyon?
Thanks, Peter.
I guess the short answer to my question is "no", which I can certainly understand, given what you are in the midst of! I would then ask if there is a means to incorporate the spin code, that provides this functionality, into a Tachyon program? I'm thinking of perhaps loading the spin code so it runs in a separate cog and has a 'hook' available to be used from Tachyon?
It's not a big job to integrate the TV code in place of the VGA in the kernel as the memory is reused for the screen memory. It's would also be possible to load the TV driver as an image from EEPROM which is one of the features planned in V3 but I will look at finishing the inline assembler to see if we could also use this as this is a more convenient way to compile PASM modules as source code.
There is one rather large reason I can't use VGA in this instance: The TFT color monitor I have is 7" and the VGA monitor I have is 28", which is too large to fit on my shelf. The TFT monitor uses an RCA plug which (under SPIN) functioned just fine with a 3-pin TV output.
Is this functionality not available in Tachyon?
I suppose if I were doing a full professional package I might try to include a lot more stuff but I've only just had time to fire up my DE2-115 for the new P2 and try some code. Somehow I don't think I might get around to integrating this although it is very similar in a lot of ways to the VGA driver. I want to fire up a version of Tachyon on the P2 now (in addition to my XMC1100 ARM parts).
You have Tachyon running on an ARM? How does it differ from the version that runs on the Propeller. I thought Tachyon was designed specifically for the Propeller architecture. Does that translate well to an ARM?
Tachyon as it is was written to suit the Prop and the restrictions and features we have both with the architecture and with the tools. But that doesn't stop it being adapted for the ARM either. The ASM kernel can still be kept as it is but the bytecode sits in the same memory space and will be much faster when I get it up and running. Then I have the option to convert some bytecode to ASM for that little extra. Even on the little XMC1100 CM0 I expect to hit close to 10 Forth MIPs. Considering that most of my Tachyon stuff runs in a single cog that's quite a performance boost even with ISRs because all the peripherals are hardware after all.
Tachyon as it is was written to suit the Prop and the restrictions and features we have both with the architecture and with the tools. But that doesn't stop it being adapted for the ARM either. The ASM kernel can still be kept as it is but the bytecode sits in the same memory space and will be much faster when I get it up and running. Then I have the option to convert some bytecode to ASM for that little extra. Even on the little XMC1100 CM0 I expect to hit close to 10 Forth MIPs. Considering that most of my Tachyon stuff runs in a single cog that's quite a performance boost even with ISRs because all the peripherals are hardware after all.
That's very interesting. How close are you to having the ARM version working? You aren't by chance porting Tachyon to the ESP8266 are you?
At $10.26USD each, that's a nice looking dev board for TachyARM!
Tachyon on an M4 ARM (STM32F4) could really be amazing!
Yeah, same chip, different package. I figured that with 16K of RAM that it would be quite useful to host a Forth as you can hold a fair bit of code in RAM until you commit to Flash plus plenty of room for bufffers. I also like the fact that it has a very wide supply voltage and is available in friendly little packages like my TSSOP16. So the idea is that this would replace many of the tiny micros I tend to use and instead of assembler or C I can just talk to it and program it at a high level from the console or from the host Prop. Should make adding these babies to boards a snap and of course the Prop can talk to the BSL of these parts to load the kernel in the first place then the Prop can act as a go-between to allow source code to be redirected to the ARM when specified. Then there are "scripts" that can be loaded at runtime too.
The M4s etc are probably next on the list as I have all sorts of eval boards for these too. Interestingly there is MeCrisp Forth for many of these ARM boards which seems to compile fast optimized code but there is not much in the way of peripheral support or OS stuff.
One of my Propeller Proto Boards (P/N: 32212) continues to go through a 'reboot' cycle as soon as I load the Explorer binary and start the serial terminal! The board works fine with a SPIN file, so I'm not suspecting the hardware, but not sure what else could cause the problem. This is the same binary I've been using all along. Any ideas?
If it's one of the Explorer versions with 1-wire support or even the autostart hardware scan then it may be "tickling" a pin that has something hooked up that is causing a problem. Other than that I would try reloading the Explorer again or even use the VGA-Explorer.
Now I am having problems with Tachyon crashing too, but that's with the P2!
I want to fire up a version of Tachyon on the P2 now (in addition to my XMC1100 ARM parts).
...
Even on the little XMC1100 CM0 I expect to hit close to 10 Forth MIPs.
Be interesting to see & compare the numbers for Tachyon on the P2, with the XMC1100 ARM parts
This board is one that has the RCA connector hooked up for 3-pin video, but the connector is not connected to anything. The is a 1-wire version of Explorer ... the only other connection made to the board is to P9, which is has a 2n2222 on it to invert the incoming serial data for Tachyon. I did have a wire hooked up to P9 just to monitor on a scope ... took that off and the problem sort of went away. Now it sometimes just works properly and sometimes (on reboot) it will go through that cycling episode I described earlier, but it eventually settles down and behaves. Not sure why, but if it "ain't broke ..."!!!
On another line of thought ... my 7219 module decided to start working again! I'd hooked it up and run one of Jon Mac's SPIN demos on it and it acted as it should. I'm not trying to get it to 'play nice' again with Tachyon ...
Hello!
I have got a bluetooth module (RN-42) to control my mouse robot.
I did connect the module to my Propeller development board. I wrote a Java app for Android which has some buttons to
control the robot via bluetooth on my mobile phone. Now I am writing the receive code in Forth.
I want to send chars like "F" for forward and "L" for left and so on. So the receive code which runs in a cog has to fetch
a single byte and store it into a variable.
This is how I did try it: (It is not parsed as OK)
TACHYON
: jimmyserial.FTH ." Jimmy the mouse bot serial receive code " ;
[~
{
The serial data receive code
}
DECIMAL
LONG serbyte
12 LONGS stack232
#P1 == prx
: RS232.TASK
stack232 SP! !SP
#115200 SERBAUD
BEGIN
prx SERIN EMIT
AGAIN
;
: serupdate ( \ update serial data )
' RS232.TASK TASK 4 RUN
]~
END
How can I store the received byte? And why is the code not correct?
jay-t,
You probably aren't seeing the output you expect because the EMIT is sending the data to the cog you're running the task in. I'm just a newbie to Tachyon, but have been playing with multiple cogs and serial input for a bit.
Hello!
I have got a bluetooth module (RN-42) to control my mouse robot.
I did connect the module to my Propeller development board. I wrote a Java app for Android which has some buttons to
control the robot via bluetooth on my mobile phone. Now I am writing the receive code in Forth.
I want to send chars like "F" for forward and "L" for left and so on. So the receive code which runs in a cog has to fetch
a single byte and store it into a variable.
This is how I did try it: (It is not parsed as OK)
TACHYON
: jimmyserial.FTH ." Jimmy the mouse bot serial receive code " ;
[~
{
The serial data receive code
}
DECIMAL
LONG serbyte
12 LONGS stack232
#P1 == prx
: RS232.TASK
stack232 SP! !SP
#115200 SERBAUD
BEGIN
prx SERIN EMIT
AGAIN
;
: serupdate ( \ update serial data )
' RS232.TASK TASK 4 RUN
]~
END
How can I store the received byte? And why is the code not correct?
there is another much more powerful and easy way to connect if you just use the bluetooth as a serial connected to the prop 30/31 pins.
Than you can not only send characters that you need to handle specially.
But insteead you have the full power of the TACHYON prompt available.
Just define some command words instead of your single characters and you have full control.
You can even download new code easily - that's hot we do it in FORTH if we can.
Thanks for this info. I have connected the bluetooth module to the TX/RX pins of the Propeller.
The commands are like "driveahead", "turnleft"... Now it works.
I just had to quickly interface to a projector so that it would turn on automatically when the screen was down and turn off when the screen when up. This required that I map the IR remote codes for the projector. I think this little utility should work with lots of remotes but I will try it out later when I have a bit more time then I will also include the transmit part of it too. I need to find some discrete power on/off codes rather than the toggle variety.
CLKFREQ #1000 / 5 * == irst --- IR minimum sync time
#P5 == irpin
long irchar
: IR_RECEIVE
irpin MASK 3 COGREG!
BEGIN
(WAITPNE) (WAITPEQ) 1 COGREG@ 0 COGREG@ - ( low duration )
DUP 2/ +
(WAITPNE) 0 COGREG@ 1 COGREG@ - ( high duration )
DUP irst >
IF
2DROP irchar ~
ELSE
> 1 AND irchar @ 2* + irchar !
THEN
AGAIN
;
--- create a table for 32 IR codes and labels (4 characters per label)
32 2* LONGS ircodes
: +CODES ircodes BEGIN DUP @ WHILE 8 + REPEAT ! ;
: +LABEL ircodes 4 + BEGIN DUP @ WHILE 8 + REPEAT 4 CMOVE ;
: IS IMMEDIATE
[COMPILE] GRAB +CODES GETWORD +LABEL
;
: .LABEL ( code -- )
ircodes BEGIN DUP @ WHILE OVER OVER @ = IF 4 + 4 CTYPE DROP EXIT THEN 8 + REPEAT 2DROP ;
--- create codes and labels ---
HEX
8F46.D7A8 IS HELP
8F46.8BF4 IS PWR
8F46.9BE4 IS UP
8F46.EB94 IS DOWN
8F46.BBC4 IS LEFT
8F46.DBA4 IS RIGHT
8F46.DFA0 IS MENU
8F46.FA85 IS ESC
8F46.FB84 IS SRC
8F46.99E6 IS AUTO
8F46.D9A6 IS SEL
8F46.B3CC IS PC
8F46.D3AC IS VID
8F46.F788 IS VOL+
8F46.EF90 IS VOL-
8F46.FD82 IS KEY+
8F46.DAA5 IS MAG+
8F46.B5CA IS MUTE
8F46.BDC2 IS KEY-
8F46.9AE5 IS MAG-
8F46.B9C6 IS BLNK
8F46.E59A IS PRE
8F46.C7B8 IS FRZ
8F46.BAC5 IS AVMUTE
8F46.E996 IS RESZ
8F46.A9D6 IS OVER
8F46.95EA IS CUST
--- listen to the IR remote and print codes and labels
: LISTEN
' IR_RECEIVE 6 RUN
BEGIN
irchar @ $8000.0000 AND IF CR irchar @ DUP .LONG SPACE .LABEL irchar ~ THEN
lastkey C@ $0D = IF CR lastkey C~ irchar ~ THEN
ESC? UNTIL
;
{ SAMPLE OUTPUT FROM LISTEN
8F46.8BF4 PWR
8F46.9BE4 UP
8F46.EB94 DOWN
8F46.B3CC PC
8F46.D3AC VID
8F46.FD82 KEY+
8F46.BDC2 KEY-
8F46.DAA5 MAG+
8F46.9AE5 MAG-
8F46.95EA CUST
}
This was a quick and dirty although it works well. The transmit code is below but I have since checked and this should be an NEC style code where they transmit 8-bit address, then the inverted address, then the 8-bit data and it's inverted data. But I can't seem to see that pattern in here though so I will have to research stuff that I have probably forgotten about
The IS word is just for constructing a sample code and label table although in practical use you would have a code lookup table which would return with the address to the 4-byte "label" data field instead of printing a label of course.
--- a more general action can be applied to codes rather than just a label.
: CODE@ ( code -- action ) ircodes BEGIN DUP @ WHILE OVER OVER @ = IF 4 + NIP EXIT THEN 8 + REPEAT 2DROP 0 ;
: .LABEL ( code -- ) CODE@ ?DUP IF 4 CTYPE THEN ;
The transmit code is about as simple as you can get and is called from the main cog normally.
#P3 == irled
: IRTX ( code -- )
irled APIN irled LOW
38 KHZ 9 ms MUTE 4500 us
32 FOR 1 ROL 38 KHZ 450 us MUTE 450 us DUP 1 AND IF 450 us THEN NEXT DROP
9 ms
;
The current code is in the Tachyon dropbox in the examples folder as NEC_REMOTE.fth
p.s. just found my old SWI2IR.fth steering wheel interface I did a few years that I've half forgotten about!
I have a device that is not playing well with the kernel I2C code. Here is the device's "exception" condition in question:
3. A falling SDA edge is not allowed between the start condition and the first rising SCL edge. If using an I2C
address with the first bit 0, SDA must be held low from the start condition through the first bit.
And attached is the logic analyzer output. The address is 0x51 or $51 so it seems SDA is allowed to pull up and then back down for the 0 which then meets condition 3. above?
Comments
Yes agreed that we mainly concentrate on the higher level words but EMIT was included because it is revectorable.
As regards to stack space you only need to set this up for anything that goes beyond the 4 level cog stack space. If the pointer isn't set then it won't try to access hub memory. However you have seen examples already and it is simply a matter of allocating some memory, perhaps using LONGS and seting the stack pointer during the startup of a task with SP! thus:
8 LONGS mystk
: MYTASK mystk SP! <and the rest> ;
Any task or cog that talks to streaming I/O such as the serial console sometimes needs to have its own I/O vectors since it may revector the EMIT to talk to the VGA screen for instance. The solution would be to have a copy of these vectors for all cogs but the trouble is that whenever you input or output you need to print numbers perhaps which converts numbers to strings before printing the string. So these cogs need to have their own copy that the Forth primitives such as KEY EMIT PRINT GETWORD and their variants use that doesn't involve anything time consuming and complex to implement.
A simple internal opcode called REG accepts an 8-bit offset from a base register as a quick and simple way to access local hub variables such as mentioned. This cuts down the need to specify a 16-bit address and while it makes the code more compact it also allows each cog to change the address stored in that base address register to use a different set of hub variables.
Now the order of the hub variables are arranged in such a way that rather than having to allocate 256 bytes of memory for another cog you only need 128 bytes since memory is limited. So therefore this is what you do to change it.
128 BYTES myregs --- allocate space for task registers (local variables)
: MYTASK
mystk SP!
myregs 7 COGREG! --- set REG base address of this cog to point to new set
<and the rest>
;
But none of those "new" registers in myregs will be initialized, they will all be zero so it is prudent to preset them by making a copy of the console cog's (cog 0) registers like this:
$24 myregs 128 CMOVE
This operation BTW can be performed during compile time without any side effects or included in your task's startup either way. The $24 is the default address of cog0's task registers and although they could be changed there isn't any reason to do so.
All this documentation makes me feel lost in space, oh the pain, the pain.
There's been a few of them going around.
Tachyon is an absolutely amazing achievement Peter!
I read up a bit on Forth on my recent flight. I didn't like it because it is the reverse of the way I think, and have been thinking for the last 40+ years, about code flow. That's my loss because I just cannot getup the motivation to use Tachyon. However, for you younger minds that haven't been corrupted like mine, jump right on in.
Just love the pics you are getting from SPLAT. I am going to need to look at this part as I am sure I could use it.
would be great to have you on board
even with arguments first and then the function name
this is nothing compared to a language that does not use western characters ;-)
it's still just a programming language
Is this functionality not available in Tachyon?
I guess the short answer to my question is "no", which I can certainly understand, given what you are in the midst of! I would then ask if there is a means to incorporate the spin code, that provides this functionality, into a Tachyon program? I'm thinking of perhaps loading the spin code so it runs in a separate cog and has a 'hook' available to be used from Tachyon?
It's not a big job to integrate the TV code in place of the VGA in the kernel as the memory is reused for the screen memory. It's would also be possible to load the TV driver as an image from EEPROM which is one of the features planned in V3 but I will look at finishing the inline assembler to see if we could also use this as this is a more convenient way to compile PASM modules as source code.
Will the ARM version run on this little guy??
At $10.26USD each, that's a nice looking dev board for TachyARM!
Tachyon on an M4 ARM (STM32F4) could really be amazing!
Yeah, same chip, different package. I figured that with 16K of RAM that it would be quite useful to host a Forth as you can hold a fair bit of code in RAM until you commit to Flash plus plenty of room for bufffers. I also like the fact that it has a very wide supply voltage and is available in friendly little packages like my TSSOP16. So the idea is that this would replace many of the tiny micros I tend to use and instead of assembler or C I can just talk to it and program it at a high level from the console or from the host Prop. Should make adding these babies to boards a snap and of course the Prop can talk to the BSL of these parts to load the kernel in the first place then the Prop can act as a go-between to allow source code to be redirected to the ARM when specified. Then there are "scripts" that can be loaded at runtime too.
The M4s etc are probably next on the list as I have all sorts of eval boards for these too. Interestingly there is MeCrisp Forth for many of these ARM boards which seems to compile fast optimized code but there is not much in the way of peripheral support or OS stuff.
Now I am having problems with Tachyon crashing too, but that's with the P2!
Be interesting to see & compare the numbers for Tachyon on the P2, with the XMC1100 ARM parts
The Nuvoton NUC4xx series are wide Supply too, and there are EvalBoards for these
http://www.nuvoton.com/hq/support/tool-and-software/development-tool-hardware/development-kit/?__locale=en
There are also XMC1402 coming, larger XMC1xxx, with CAN, 48&96MHz and Maths co-pro.
This board is one that has the RCA connector hooked up for 3-pin video, but the connector is not connected to anything. The is a 1-wire version of Explorer ... the only other connection made to the board is to P9, which is has a 2n2222 on it to invert the incoming serial data for Tachyon. I did have a wire hooked up to P9 just to monitor on a scope ... took that off and the problem sort of went away. Now it sometimes just works properly and sometimes (on reboot) it will go through that cycling episode I described earlier, but it eventually settles down and behaves. Not sure why, but if it "ain't broke ..."!!!
On another line of thought ... my 7219 module decided to start working again! I'd hooked it up and run one of Jon Mac's SPIN demos on it and it acted as it should. I'm not trying to get it to 'play nice' again with Tachyon ...
I have got a bluetooth module (RN-42) to control my mouse robot.
I did connect the module to my Propeller development board. I wrote a Java app for Android which has some buttons to
control the robot via bluetooth on my mobile phone. Now I am writing the receive code in Forth.
I want to send chars like "F" for forward and "L" for left and so on. So the receive code which runs in a cog has to fetch
a single byte and store it into a variable.
This is how I did try it: (It is not parsed as OK)
How can I store the received byte? And why is the code not correct?
You probably aren't seeing the output you expect because the EMIT is sending the data to the cog you're running the task in. I'm just a newbie to Tachyon, but have been playing with multiple cogs and serial input for a bit.
there is another much more powerful and easy way to connect if you just use the bluetooth as a serial connected to the prop 30/31 pins.
Than you can not only send characters that you need to handle specially.
But insteead you have the full power of the TACHYON prompt available.
Just define some command words instead of your single characters and you have full control.
You can even download new code easily - that's hot we do it in FORTH if we can.
And no extra COG and complications needed..
The commands are like "driveahead", "turnleft"... Now it works.
I just had to quickly interface to a projector so that it would turn on automatically when the screen was down and turn off when the screen when up. This required that I map the IR remote codes for the projector. I think this little utility should work with lots of remotes but I will try it out later when I have a bit more time then I will also include the transmit part of it too. I need to find some discrete power on/off codes rather than the toggle variety.
EDIT: Here is a cleaner version of the IS word:
This was a quick and dirty although it works well. The transmit code is below but I have since checked and this should be an NEC style code where they transmit 8-bit address, then the inverted address, then the 8-bit data and it's inverted data. But I can't seem to see that pattern in here though so I will have to research stuff that I have probably forgotten about
The IS word is just for constructing a sample code and label table although in practical use you would have a code lookup table which would return with the address to the 4-byte "label" data field instead of printing a label of course.
--- a more general action can be applied to codes rather than just a label.
The transmit code is about as simple as you can get and is called from the main cog normally.
The current code is in the Tachyon dropbox in the examples folder as NEC_REMOTE.fth
p.s. just found my old SWI2IR.fth steering wheel interface I did a few years that I've half forgotten about!
3. A falling SDA edge is not allowed between the start condition and the first rising SCL edge. If using an I2C
address with the first bit 0, SDA must be held low from the start condition through the first bit.
And attached is the logic analyzer output. The address is 0x51 or $51 so it seems SDA is allowed to pull up and then back down for the 0 which then meets condition 3. above?