|
In article <38EFD9B7.6CD8E68C@SPAM.netstrata.com>, Dennis Williamson
<dennis.NO@SPAM.netstrata.com> wrote:
> Have you considered adding the firmware build version to that symbol or
> to a
> new one?
>
> __RCX = 2
This first define (__RCX = 2) will happen automatically in NQC when you
select RCX 2.0 as the target for compilation. Selecting an RCX 1.0
target will cause the symbol to be defined as 1.
> __FIRMWARE=3.21
I hope I don't have to add a __FIRMWARE symbol...
Hopefully, there won't be too many versions of firmware out there.
There's only one 1.0 firmware (3.09). We'll probably see a bunch of 2.0
firmware versions, but that's just because we're getting to see the
entire alpha/beta cycle. I wouldn't expect feature changes or new
capabilities at this point from one version to the next (especially
after 2.0 goes final) - just bug fixes. Also, I would hope that
everything but the latest and greatest 2.0 firmware would be very
short-lived. Thus, I really only expect two RCX targets from an NQC
perspective: 1.0 and 2.0.
> This would facilitate creation of portable, work-around code that would
> accomodate an end-user who hasn't updated their firmware (or has a reason
> not
> to). It could also be useful in comparing code functionality side-by-side
> on
> two firmware versions.
Portable source code or portable binary code?
Creating a single binary that can run on 1.0 but also take advantage of
2.0 features when present is tricky. Solving the binary problem is more
complicated than solving the problem of portable source. Furthermore,
any portable binary would undoubtedly be larger than the specialized
binaries (1.0 and 2.0) generated from portable source. Last, the vast
majority of NQC code is shared in source form rather than binary, so the
need for portable binaries is pretty minimal compared to the need for
portable source.
This being the case, I'd prefer to focus on the functionality and
practices of writing portable source.
IMHO, the steps to this are:
1) Binary backwards compatability. Ideally a 2.0 RCX should be able to
run any 1.0 program. Lego is aiming for this, and so far seems to have
achieved it.
2) Source backwards compatability. Every RCX 1.0 NQC source program is
also a legal RCX 2.0 NQC source program. This is a high priority for
me...in fact I won't get very far in my regression tests for NQC if I
mess this up in any significant way.
3) When compiling a 2.0 program, those features that are possible in 1.0
should be primarily exposed via APIs that are identical to the 1.0 APIs.
In other words, don't gratuitously add new APIs in 2.0 to get at
features which were already available with 1.0 APIs. Extension of this
rule would also suggest that features common to the Scout ahd RCX 2.0
share identical APIs.
4) Use compile-time symbols to indicate the target of the compilation.
This way, if someone wants to use an RCX 2.0 feature, but has a suitable
workaround if it isn't there, they can code it conditionally.
5) Provide 'stub' functionality for various 2.0 APIs when compiled for a
1.0 target. This has been my lowest priority so far. Part of the
reason is that it makes me a bit nervous to have the compiler nop API
calls simply because the target can't support them (a).
Lego is taking care of #1. Initial release of NQC 2.2 (or whatever the
version that supports RCX 2.0) should address #2, #3, and #4. Item #5
will probably come later, if at all.
Dave Baum
(a) Here's an example...
The CyberMaster only supports touch sensors, so a call like
SetSensorType() has no meaning. Now the simple case is a program like
this:
task main
{
SetSensorType(SENSOR_1, SENSOR_TYPE_TOUCH);
// now do something...
}
When compiled for a CyberMaster, it will generate an error
(SetSensorType() not defined). Some would say that I should have
defined SetSensorType() as a nop so the program would still compile.
After all, on a CyberMaster, you don't need to do anything to set the
sensor to touch. What then should be done here:
task main
{
SetSensorType(SENSOR_1, SENSOR_TYPE_LIGHT);
// now do something...
}
I don't think its a good idea to let this program compile without an
error. The program clearly expects a light sensor (or something
similar) to be attached to port 1, and the target just can't do that.
IMHO, ignoring code is just plain wrong. It would almost be like NQC
allowing 33 variables to be declared knowing full well that only 32 are
available.
The best thing then would be for the compiler to be able to distinguish
between the nop and error case. I don't think '#pragma error' will do
the trick because the error probably has to be detected at macro
expansion rather than definition and as a rule preprocessor directives
get processed during macro definition. However, if someone has some
clever ideas on how '#pragma error' could be used, please let me know.
Probably an "error" keyword of some type and also relying on the fact
that constant evaluation and comparisson takes place at compile time
would do the trick:
#ifdef __RCX
void SetSensorType(__sensor sensor, const int type) { asm { 0x32,
&sensor : 0x03000200, (type) }; }
#else
// this is for cybermaster
void SetSensorType(__sensor sensor, const int type)
{
if (type != SENSOR_TYPE_TOUCH)
error("CyberMaster only support touch sensors");
}
#endif
THe problem here is that the API is now relying on some very subtle
behavior in the compiler and adding a very non-traditional feature (the
'error' keyword) - sort of a blurring between compile and run-time.
I've seen templates used to blur this line, but it always makes me
uncomfortable (anyone want to calculate fibonacci numbers at compile
time?).
Since I feel so strongly that the second program must generate an error
and I don't have a good way to differentiate between the first and
second programs at compile time, I've gone the route of forcing an error
for both programs.
If anyone has some suggestions on a reasonable way to distinguish the
two programs at compile time and conditionally generate an error, please
let me know.
--
reply to: dbaum at enteract dot com
|
|
Message has 2 Replies: | | Re: NQC Ignores based on your pbrink
|
| (...) This seems reasonable to me. Plus, it has the added benefit of being inherently open: source is all about "here's how to do this"; binaries are "here's a thing that does this". It's nice to encourage the first attitude. (25 years ago, 9-Apr-00, to lugnet.robotics.rcx.nqc)
| | | Re: NQC Ignores based on your pbrink
|
| I definitely intended to mean portable source. And that the "__FIRMWARE" would be used in compiler directives rather than in the code. It is a simple matter for me to define my own __FIRMWARE (or anything else, right?) and do #ifdef's to my heart's (...) (25 years ago, 9-Apr-00, to lugnet.robotics.rcx.nqc)
|
Message is in Reply To:
| | Re: NQC Ignores based on your pbrink
|
| Have you considered adding the firmware build version to that symbol or to a new one? __RCX = 2 __FIRMWARE=3.21 This would facilitate creation of portable, work-around code that would accomodate an end-user who hasn't updated their firmware (or has (...) (25 years ago, 9-Apr-00, to lugnet.robotics.rcx.nqc)
|
10 Messages in This Thread:
- Entire Thread on One Page:
- Nested:
All | Brief | Compact | Dots
Linear:
All | Brief | Compact
This Message and its Replies on One Page:
- Nested:
All | Brief | Compact | Dots
Linear:
All | Brief | Compact
|
|
|
|