The debate over Catalina versus PropGCC is silly, and we should focus more on C code that runs under either compiler.
Of course, for someone that wants to write object oriented code in C++ they would need to use PropGCC.
I agree on all counts. I would like to see Catalina compile the Learn library for example.
One problem will be with attributes though. Does Catalina have something equivalent to __attribute__((fcache)) ? That gets used in the simple serial library for doing 115200 bps without having to waste a COG.
For xmm modes we can also force xmm code to run in HUB with HUBTEXT or build code that runs in a COG with .cogc . Those are less of a problem, but often it's useful to have the speed. One of my latest projects is a port of Andy's .wav player to xmmc mode using .cogc and HUBTEXT. Miraculously the file system throughput went to over 190KB/s.
This FFT port comes up quite a bit almost as if it were a RGB (255,0,0) herring. If I need FFT on an embedded system it's time for A. micro-computer or B. a cheap ALU chip
This herring is most definitely not red,
That FFT has been used in at least two successful projects described in detail on this forum, A power factor meter and an instrument tuning device. Other similar transforms have also been used. See the sound analyzer YouTube link earlier in this thread.
Certainly I did not imagine it would get used when I wrote it. It was just a fun exercise at the time. And certainly if you need a more accurate, or bigger, or faster FFT you will want something other than a P1. But if it's good enough to do what you want to do and allows you to use all the other nice Prop features then why not?
Your solution A) seems like it will be bigger, more complex, and your lose the real-time deterministic multi-processing features of he Prop.
As for solution What is a cheap ALU chip? The only one I know is the obsolete TTL 74181 which is not going to help you. Or the also obsolete bit slice chips from AMD which also won't help.
I tried to get you involved with PropGCC a number of times but you didn't seem interested. I still think you could make a big contribution to the project. As has been pointed out before, one reason Parallax decided to go with GCC instead of LCC (which is the basis of Catalina) is because GCC supports C++ as well as C. It also has a better optimizer. In any case, the majority of the work you've done on Catalina seems to be in the area of runtime support and libraries and PropGCC is in need of that sort of work as well. Is there any chance we could find a way to merge our efforts rather than trying to outdo each other? It seems like that would be the best way forward. Like it or not, the Parallax C offering will be based on GCC but that doesn't mean we can't work together. The compiler itself is only one piece of the entire C/C++ system.
Hi David,
Having GCC available on the Propeller is unambiguously a "good thing". At one point I was interested in joining the GCC team - but we both know why that was never really going to happen. If you want to discuss that issue further, let's do so via PM, and not pollute this thread.
I'll just make a couple of points here that I think are in the original spirit of this thread:
Even though having GCC available is good, it is not the answer to everything. It never met my needs, for instance, and doesn't look like it ever will. There are others in the same situation. This is not criticism of GCC - there is no "one size fits all" solution here, and having multiple C compilers is a good thing, not a bad thing.
For the P1, the OBEX was one of the greatest attractions of the Propeller. It allowed newcomers with little programming experience to develop sophisticated programs fast. The fact that the OBEX can't easily be exploited from other languages (not only C) is a tragedy that should never have been allowed to happen on the P1, and should not be allowed to happen again on the P2. Catalina tries to address that gap. I can write OBEX objects that are 100% compatible (and equally easy to use) from either Spin or C. Also, most existing OBEX objects could easily be modified to make this possible - the changes required are quite trivial.
It's not silly if Catalina is able to link Spin objects into a C program directly, as Ross implies. ('Guess I just need to try it and see.)
I don't think it works that way. The Catalina C kernel would need to include a Spin interpreter to be able to do that. I'm guessing that the Catalina library contains C versions of the Spin drivers that talk to PASM code the same way the Spin code does. Maybe Ross can elaborate on it when it's daylight in his part of the world.
spin2cpp allows C code to work with Spin by converting it to C, which seems like a reasonable approach. You can still write code in Spin, but it get's compiled into a C executable. The other approach is to talk to Spin code running in another cog using a mailbox.
It's not silly if Catalina is able to link Spin objects into a C program directly, as Ross implies. ('Guess I just need to try it and see.)
-Phil
Hi Phil.
Below is an extract from the README.txt in Catalina's demo/spinc folder. Now, before I get torrents of complaints, I know spinc is not unique to Catalina. It was developed by jazzed, and I think GCC uses it as well. But the degree of possible integration with Catalina is what is important. I have added comments about the significant parts in red.
run_hello.binary - demonstrates a Spin program (hello.spin) that makes
use of whatever HMI plugin has been loaded by Catalina.
Also uses the file "Catalina_HMI.spin" which provides
wrapper functions for all Catalina HMI functions.
[COLOR=#b22222][B]i.e. Spin programs can execute with C and the Spin programs use the drivers loaded by the C program.[/B][/COLOR]
run_demo.binary - runs the demo program for Bagger's 40*30 TV driver. This
demo is interesting because while the TV driver demo is
running, Catalina is running using serial HMI drivers.
[COLOR=#b22222][B]i.e. Spin programs can execute completely unmodified alongside C programs (I think GCC can probably do this one as well - not sure).[/B][/COLOR]
run_kb_tv.binary - run a simple terminal program that accepts keystrokes
and echoes them on the terminal, translating any numeric
keys to strings. This is interesting because it is using
standard OBEX drivers for HMI functions instead of the
normal Catalina HMI functions.
[COLOR=#b22222][B]i.e. Spin programs can execute with C and the C programs can use drivers loaded by the Spin program.[/B][/COLOR]
Plus of course, you can simply invoke entire Spin programs from C, or call PASM functions from C (it is currently not possible to do the reverse). Naturally, there are limitations on what you can do, since Spin was never designed for this, and many Spin/PASM programs just splat themselves over all available Propeller resources because they didn't make allowance for being invoked this way.
On second thought, I assumed my quote made no sense, since you have to load the ROM interpreter into a cog first. Does Catalina swap its kernel for the interpreter on call, or do you have a remote procedure protocol for inter-cog method calls?
On second thought, I assumed my quote made no sense, since you have to load the ROM interpreter into a cog first. Does Catalina swap its kernel for the interpreter on call, or do you have a remote procedure protocol for inter-cog method calls?
-Phil
Maybe it's me who misunderstood - Catalina starts another cog executing with the Spin interpreter to run the Spin program.
There is a well-defined standard for interacting with any cog "objects" that either the C program or the Spin program start, so they can share these very easily - but any direct communication between the Spin code and the C code you have to arrange for yourself. It would make sense to have a standard technique for that (actually, there already is one - just use the registry), and also another that allows a method in the executing Spin program to be called as if it was a C function, but that would probably require deep interrogation of the compiled Spin code - and also a lot of frigging about.
I'll have a think about it, but I'm not sure its worth all the trouble.
What I would really like to see -- especially for teaching C -- is a C compiler that compiles to Spin bytecodes. It would be simple, without all the futz about different memory models. Granted, you don't get C's speed advantage as a "high-level assembler", but for pedagogical purposes, who cares? -- especially, since Parallax's C thrust seems to be aimed at schools, not industry. Even "C-lite" would be okay for this. Parallax's "learn" library is so complete that my students are only learning dumbed-down C as it is.
I don't think you need a special version of C that compiles to Spin byte codes to make life simple for teaching.
Sounds like what you need is a version of SimpleIDE built without all the multi-language, multi-memory model and most other options. Probably remove all the board type options if you know here is only one board in use in class.
That way it reduces to: Write C code, hit compile/load button. Just like Spin and just like the Arduino IDE.
Below is an extract from the README.txt in Catalina's demo/spinc folder. Now, before I get torrents of complaints, I know spinc is not unique to Catalina. It was developed by jazzed, and I think GCC uses it as well. But the degree of possible integration with Catalina is what is important. I have added comments about the significant parts in red.
run_hello.binary - demonstrates a Spin program (hello.spin) that makes
use of whatever HMI plugin has been loaded by Catalina.
Also uses the file "Catalina_HMI.spin" which provides
wrapper functions for all Catalina HMI functions.
[COLOR=#b22222][B]i.e. Spin programs can execute with C and the Spin programs use the drivers loaded by the C program.[/B][/COLOR]
run_demo.binary - runs the demo program for Bagger's 40*30 TV driver. This
demo is interesting because while the TV driver demo is
running, Catalina is running using serial HMI drivers.
[COLOR=#b22222][B]i.e. Spin programs can execute completely unmodified alongside C programs (I think GCC can probably do this one as well - not sure).[/B][/COLOR]
run_kb_tv.binary - run a simple terminal program that accepts keystrokes
and echoes them on the terminal, translating any numeric
keys to strings. This is interesting because it is using
standard OBEX drivers for HMI functions instead of the
normal Catalina HMI functions.
[COLOR=#b22222][B]i.e. Spin programs can execute with C and the C programs can use drivers loaded by the Spin program.[/B][/COLOR]
Plus of course, you can simply invoke entire Spin programs from C, or call PASM functions from C (it is currently not possible to do the reverse). Naturally, there are limitations on what you can do, since Spin was never designed for this, and many Spin/PASM programs just splat themselves over all available Propeller resources because they didn't make allowance for being invoked this way.
Ross.
Catalina is clearly ahead at integrating C and Spin. With PropGCC you have basically two options, you can extract the DAT section of a PASM program and load it into a COG to use as a driver. To do this you have to recode the Spin interface in C. The other option is to use spin2cpp to compile an entire Spin program to C++. I'm interested in learning more about how you use spinc. Do you use it to translate entire Spin programs to C like Eric does with his spin2cpp program?
Anyway, when I started working on propgcc I had naively thought that we could join efforts to try to make the best possible C/C++ system for the Propeller but I guess we're doomed to trying to outdo each other. I'm sorry it has come to this and I would be happy to talk about how we could change this and work together. There are enough opponents to C on the Propeller that we don't need the C community fractured into the PropGCC and the Catalina camps. You say options are good but I'm not sure that's true in this case.
Anyway, when I started working on propgcc I had naively thought that we could join efforts to try to make the best possible C/C++ system for the Propeller but I guess we're doomed to trying to outdo each other. I'm sorry it has come to this and I would be happy to talk about how we could change this and work together. There are enough opponents to C on the Propeller that we don't need the C community fractured into the PropGCC and the Catalina camps. You say options are good but I'm not sure that's true in this case.
I certainly don't see it as trying to "outdo" each other. If the GCC team sees it this way, then I can only say they are worrying needlessly. If you want to use C++ on the Propeller, you have to use GCC - you have no option. If you want to use C, then you have the option of using GCC or Catalina. They take different approaches and offer different benefits.
Parallax's "learn" library is so complete that my students are only learning dumbed-down C as it is.
-Phil
I'm thinking about this a lot. I teach teen students interested in STEM and adult hobbyists/educators/artists.
When I use What's a Microcontroller's lesson on servos they learn how to create a train of pulses and modify each part. I think that is useful for understanding all future communication techniques. Now in Prop C I am unsure what to do with the libraries.
For teens, if I approach servos through the library then I feel the lesson is, as PhiPi described, dumbed-down. It would be an opportunity to study pulse trains that is not used. My approach for now for students is to frame the chapter as a lesson in pulse trains and servos. Then do most of chapter without library and add .h in for the last third.
The hobbyists or teachers are mostly coming from PBASIC to Prop C, but only because I am making a hard sell. I encourage them to recall the lines of code to control a servo in PBASIC and note that in PropC the functions are already made. Those folks already understand a pulse train so I'm not as concerned that they want to grab the library and get on with the rest of the project. I don't feel a responsibility for their long-term education.
This come back to my thoughts on teaching in the age of Google, YouTube and fora. The teacher is no longer a dispenser of knowledge. The role of a teacher is now 1) select what to teach & in what order, 2) create exercises, 3) troubleshoot student projects (especially hardware). How to use PropC libraries exemplifies the first task.
I certainly don't see it as trying to "outdo" each other. If the GCC team sees it this way, then I can only say they are worrying needlessly. If you want to use C++ on the Propeller, you have to use GCC - you have no option. If you want to use C, then you have the option of using GCC or Catalina. They take different approaches and offer different benefits.
I really don't see how this can be a bad thing.
Ross.
Okay, I guess we continue to go our own ways. The PropGCC team is not "worrying". As I've said elsewhere, I'm just sorry that we can't combine efforts to make something that might satisfy both of us and provide a stronger offering to the Propeller community.
Okay, I guess we continue to go our own ways. The PropGCC team is not "worrying". As I've said elsewhere, I'm just sorry that we can't combine efforts to make something that might satisfy both of us and provide a stronger offering to the Propeller community.
Hi David,
The PropGCC team is free to pick up anything in Catalina they feel would be useful to them. I'll even help out it if they need further explanations or assistance. Also, if they want to make changes that I believe I can incorporate back into Catalina, then in the interests of compatibility I'm happy to do so.
This offer has been made by me several times before. Short of actually implementing it for them, I'm not sure what else I can do.
The PropGCC team is free to pick up anything in Catalina they feel would be useful to them. I'll even help out it if they need further explanations or assistance. Also, if they want to make changes that I believe I can incorporate back into Catalina, then in the interests of compatibility I'm happy to do so.
This offer has been made by me several times before. Short of actually implementing it for them, I'm not sure what else I can do.
Ross.
Thanks for your offer. Yes, I remember you making a similar offer in the past. I need to look over your solution for incorporating Spin code in a C program. I guess I'll look over your documentation to understand better how you handle that and I'll get back to you if I have any questions.
Thanks for your offer. Yes, I remember you making a similar offer in the past. I need to look over your solution for incorporating Spin code in a C program. I guess I'll look over your documentation to understand better how you handle that and I'll get back to you if I have any questions.
Thanks,
David
Okay, I've looked at spinc and I think I understand what it does. It pretty much does the same thing that we do with spin2cpp or openspin to extract the DAT section of a Spin object to load as a COG driver. However, it has the additional feature of being able to extract the entire Spin program and generate a function to load and start it. That's handy and would probably be a good addition to PropGCC. Thanks for pointing it out. Now if only we had a good way to generate the C wrapper functions that are needed to call the Spin code. Have you come up with a solution to that? If so, can you point me to where that is in the Catalina code?
This offer has been made by me several times before. Short of actually implementing it for them, I'm not sure what else I can do.
What offer are you talking about exactly? My memory just needs a little refresh in this case. Anything short of an architectural change is probably easy.
I do seem to remember Ross making such an offer before. It seems to extend to borrowing techniques and ideas to wholesale reuse of code within propgcc. Assuming there are no license issues. I would presume Ross would be happy to accommodate that as well if asked. And the willingness to answer any questions. Everything short of actually working on propgcc.
I should not speak for Ross but that seems a fair enough offer. These are opensource and Free Software projects right? So forking, cutting and pasting and so on are valid software engineering techniques.
Heck I was reading just the other day that the GCC and Clang/LLVM teams have expressed an intent to cooperate in making their compilers more compatible and interchangeable for users and within other software development tools.
I do seem to remember Ross making such an offer before. It seems to extend to borrowing techniques and ideas to wholesale reuse of code within propgcc. Assuming there are no license issues. I would presume Ross would be happy to accommodate that as well if asked. And the willingness to answer any questions. Everything short of actually working on propgcc.
I should not speak for Ross but that seems a fair enough offer. These are opensource and Free Software projects right? So forking, cutting and pasting and so on are valid software engineering techniques.
Heck I was reading just the other day that the GCC and Clang/LLVM teams have expressed an intent to cooperate in making their compilers more compatible and interchangeable for users and within other software development tools.
Cats and dogs lying together and all that.
Actually, now that I think about it, I made a similar offer to Ross a while back. So I guess we at least have the potential of cooperating.
Does anyone think the constant arguing makes this forum seem like a place where new people might want to hang out and learn about the propeller?
There are so many talented people here and the P1 still has a lot to offer and the P2 is coming along nicely now, so can we focus on positive stuff?
Big deal if we have more than one "C", and a bunch of FORTHs, and BASIC's, and SPIN, and PASM, and GAS and...
It just proves the P1 is flexible and fun to work with.
For some people their projects are "end use" finished projects like clocks, robots, etc., for some they are hardware platforms, for others they are languages and other development tools.
Who gets to choose what is valid and worthy of discussion?
I understand the urge to focus on an 'official' set of things so new people can easily be pointed in a helpful direction, but does that come at the price of making others feel unwelcome if the are doing something that may challenge the status quo?
So this "offer" was to include support for the over complicated registry feature that wastes a cog?
Does the registry really use a COG? I thought it was only a passive data structure in high hub memory. Maybe it's the HMI that takes a COG but doesn't that also handle stdin/stdout?
Does anyone think the constant arguing makes this forum seem like a place where new people might want to hang out and learn about the propeller?
There are so many talented people here and the P1 still has a lot to offer and the P2 is coming along nicely now, so can we focus on positive stuff?
Big deal if we have more than one "C", and a bunch of FORTHs, and BASIC's, and SPIN, and PASM, and GAS and...
It just proves the P1 is flexible and fun to work with.
For some people their projects are "end use" finished projects like clocks, robots, etc., for some they are hardware platforms, for others they are languages and other development tools.
Who gets to choose what is valid and worthy of discussion?
I understand the urge to focus on an 'official' set of things so new people can easily be pointed in a helpful direction, but does that come at the price of making others feel unwelcome if the are doing something that may challenge the status quo?
Chris Wardell
I don't want anyone to feel like what they are doing is unwelcome. I'm just selfishly wanting to take advantage of the best talent here to advance PropGCC which happens to be my current project and I certainly count RossH among those people.
Comments
One problem will be with attributes though. Does Catalina have something equivalent to __attribute__((fcache)) ? That gets used in the simple serial library for doing 115200 bps without having to waste a COG.
For xmm modes we can also force xmm code to run in HUB with HUBTEXT or build code that runs in a COG with .cogc . Those are less of a problem, but often it's useful to have the speed. One of my latest projects is a port of Andy's .wav player to xmmc mode using .cogc and HUBTEXT. Miraculously the file system throughput went to over 190KB/s.
That FFT has been used in at least two successful projects described in detail on this forum, A power factor meter and an instrument tuning device. Other similar transforms have also been used. See the sound analyzer YouTube link earlier in this thread.
Certainly I did not imagine it would get used when I wrote it. It was just a fun exercise at the time. And certainly if you need a more accurate, or bigger, or faster FFT you will want something other than a P1. But if it's good enough to do what you want to do and allows you to use all the other nice Prop features then why not?
Your solution A) seems like it will be bigger, more complex, and your lose the real-time deterministic multi-processing features of he Prop.
As for solution What is a cheap ALU chip? The only one I know is the obsolete TTL 74181 which is not going to help you. Or the also obsolete bit slice chips from AMD which also won't help.
-Phil
http://www.ti.com/lit/ds/symlink/tms320c5532.pdf
at 1.95 SPI and you have the world of math + a highly precise FFT
Ultra low power 3.3v to boot!
Hi David,
Having GCC available on the Propeller is unambiguously a "good thing". At one point I was interested in joining the GCC team - but we both know why that was never really going to happen. If you want to discuss that issue further, let's do so via PM, and not pollute this thread.
I'll just make a couple of points here that I think are in the original spirit of this thread:
- Even though having GCC available is good, it is not the answer to everything. It never met my needs, for instance, and doesn't look like it ever will. There are others in the same situation. This is not criticism of GCC - there is no "one size fits all" solution here, and having multiple C compilers is a good thing, not a bad thing.
- For the P1, the OBEX was one of the greatest attractions of the Propeller. It allowed newcomers with little programming experience to develop sophisticated programs fast. The fact that the OBEX can't easily be exploited from other languages (not only C) is a tragedy that should never have been allowed to happen on the P1, and should not be allowed to happen again on the P2. Catalina tries to address that gap. I can write OBEX objects that are 100% compatible (and equally easy to use) from either Spin or C. Also, most existing OBEX objects could easily be modified to make this possible - the changes required are quite trivial.
Ross.Cool device. I don't expect to be playing with one any time soon though.
spin2cpp allows C code to work with Spin by converting it to C, which seems like a reasonable approach. You can still write code in Spin, but it get's compiled into a C executable. The other approach is to talk to Spin code running in another cog using a mailbox.
-Phil
Hi Phil.
Below is an extract from the README.txt in Catalina's demo/spinc folder. Now, before I get torrents of complaints, I know spinc is not unique to Catalina. It was developed by jazzed, and I think GCC uses it as well. But the degree of possible integration with Catalina is what is important. I have added comments about the significant parts in red.
Plus of course, you can simply invoke entire Spin programs from C, or call PASM functions from C (it is currently not possible to do the reverse). Naturally, there are limitations on what you can do, since Spin was never designed for this, and many Spin/PASM programs just splat themselves over all available Propeller resources because they didn't make allowance for being invoked this way.
Ross.
This is what Catalina does.
-Phil
Maybe it's me who misunderstood - Catalina starts another cog executing with the Spin interpreter to run the Spin program.
There is a well-defined standard for interacting with any cog "objects" that either the C program or the Spin program start, so they can share these very easily - but any direct communication between the Spin code and the C code you have to arrange for yourself. It would make sense to have a standard technique for that (actually, there already is one - just use the registry), and also another that allows a method in the executing Spin program to be called as if it was a C function, but that would probably require deep interrogation of the compiled Spin code - and also a lot of frigging about.
I'll have a think about it, but I'm not sure its worth all the trouble.
Ross.
-Phil
I don't think you need a special version of C that compiles to Spin byte codes to make life simple for teaching.
Sounds like what you need is a version of SimpleIDE built without all the multi-language, multi-memory model and most other options. Probably remove all the board type options if you know here is only one board in use in class.
That way it reduces to: Write C code, hit compile/load button. Just like Spin and just like the Arduino IDE.
SimpleIDE is just not simple any more.
Anyway, when I started working on propgcc I had naively thought that we could join efforts to try to make the best possible C/C++ system for the Propeller but I guess we're doomed to trying to outdo each other. I'm sorry it has come to this and I would be happy to talk about how we could change this and work together. There are enough opponents to C on the Propeller that we don't need the C community fractured into the PropGCC and the Catalina camps. You say options are good but I'm not sure that's true in this case.
I certainly don't see it as trying to "outdo" each other. If the GCC team sees it this way, then I can only say they are worrying needlessly. If you want to use C++ on the Propeller, you have to use GCC - you have no option. If you want to use C, then you have the option of using GCC or Catalina. They take different approaches and offer different benefits.
I really don't see how this can be a bad thing.
Ross.
I'm thinking about this a lot. I teach teen students interested in STEM and adult hobbyists/educators/artists.
When I use What's a Microcontroller's lesson on servos they learn how to create a train of pulses and modify each part. I think that is useful for understanding all future communication techniques. Now in Prop C I am unsure what to do with the libraries.
For teens, if I approach servos through the library then I feel the lesson is, as PhiPi described, dumbed-down. It would be an opportunity to study pulse trains that is not used. My approach for now for students is to frame the chapter as a lesson in pulse trains and servos. Then do most of chapter without library and add .h in for the last third.
The hobbyists or teachers are mostly coming from PBASIC to Prop C, but only because I am making a hard sell. I encourage them to recall the lines of code to control a servo in PBASIC and note that in PropC the functions are already made. Those folks already understand a pulse train so I'm not as concerned that they want to grab the library and get on with the rest of the project. I don't feel a responsibility for their long-term education.
This come back to my thoughts on teaching in the age of Google, YouTube and fora. The teacher is no longer a dispenser of knowledge. The role of a teacher is now 1) select what to teach & in what order, 2) create exercises, 3) troubleshoot student projects (especially hardware). How to use PropC libraries exemplifies the first task.
Hi David,
The PropGCC team is free to pick up anything in Catalina they feel would be useful to them. I'll even help out it if they need further explanations or assistance. Also, if they want to make changes that I believe I can incorporate back into Catalina, then in the interests of compatibility I'm happy to do so.
This offer has been made by me several times before. Short of actually implementing it for them, I'm not sure what else I can do.
Ross.
Thanks,
David
Thanks!
David
I should not speak for Ross but that seems a fair enough offer. These are opensource and Free Software projects right? So forking, cutting and pasting and so on are valid software engineering techniques.
Heck I was reading just the other day that the GCC and Clang/LLVM teams have expressed an intent to cooperate in making their compilers more compatible and interchangeable for users and within other software development tools.
Cats and dogs lying together and all that.
There are so many talented people here and the P1 still has a lot to offer and the P2 is coming along nicely now, so can we focus on positive stuff?
Big deal if we have more than one "C", and a bunch of FORTHs, and BASIC's, and SPIN, and PASM, and GAS and...
It just proves the P1 is flexible and fun to work with.
For some people their projects are "end use" finished projects like clocks, robots, etc., for some they are hardware platforms, for others they are languages and other development tools.
Who gets to choose what is valid and worthy of discussion?
I understand the urge to focus on an 'official' set of things so new people can easily be pointed in a helpful direction, but does that come at the price of making others feel unwelcome if the are doing something that may challenge the status quo?
Chris Wardell