My idea of fully-portable C code

The reasoning behind that choice of encoding is flawed. Putting an unused state in the middle of a list of values will "use the least amount of memory possible" only by luck, but never by design.

Here's your first unwarranted assumption (although it's not one of portability). You've validated your self-stated requirement:

Using uint8_fast_t for the datatype disallows setting the chunk size to more than 8 bits.

In addition to that, 'i' should really be size_t or something at least as large as that. As-is, you introduce yet another hardcoded limitation.

Bad macro. Parentheses missing around QUANTITY_CHUNKS and BITS_PER_CHUNK leave the code vulnerable to funny definitions of those constants (e.g. #define BITS_PER_CHUNK 2+3) The same problem occurs repeatedly later on.

And it has a portability problem, too! Check out what this does for QUANTITY_CHUNKS=60000u, BITS_PER_CHUNK=6u, on a 16-bit host platform. You lose. Thanks for playing.

16-bit platform).

... so this fails if I set BITS_PER_CHUNK to more than the number of bits in an unsigned int (after lifting the earlier restriction about uint8_fast_t).

Well, it doesn't fulfill that promise. And that not just on some conceivable implementation of the C89 standard, but actually on entire

*class* of systems that are in wide-spread usage.
Reply to
Hans-Bernhard Bröker
Loading thread data ...

You said

If you only have experience of one MCU how can you even suggest that you know how to write portable code?

You would need real experience of several MCU before even suggesting you could write portable code.

Thus far you have not shown anything to back up your claim.

--
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
\/\/\/\/\ Chris Hills  Staffs  England     /\/\/\/\/
 Click to see the full signature
Reply to
Chris H

I'd put the abstraction at the level of a "LED array", which would be a module responsible for driving an array of LEDs.

My version of the interface would be something like this:

void set_led_color( int led, int color );

The module would hide the peculiarities of the CPU, the hardware multiplex design, and memory layout restrictions. Given that most of the module needs to be rewritten anyway in case it is ported to a different design, I would not worry about portability of the module code itself.

This approach allows simpler code (assume 4 LEDs / byte) and better optimization since I can pick a memory layout that fits the hardware, while keeping the interface to the outside world exactly the same. I consider the last part a more important version of portability.

Reply to
Arlet Ottens

I don't think I get it. It is my understanding that this is supposed to be portable microcontroller code. Alright, what are printf and puts doing in main? Who said there was a screen to print to? That won't work on my embedded AVR app.

In fact, where does your code have any interface with the outside world? Where do you read or set the current status of the LED's you talk about? Wouldn't this require reading and writing a register, which is inherently specific to a platform? Do you want to use a UART to send those messages in the printf and puts? Maybe there are two to choose from. It seems to me that as soon as you want to interface to the outside world in an embedded app, you need to do something that is device-specific. Doing things internally, with no external visibility and no way to talk to the rest of the system, and saying its portable is not very useful.

Am I missing something?

Dave

Reply to
Dave

ht

=3D

tes

Precisely, unless you were making a toy and probably for this using=20 a 4 bit processor or for that matter for this type of application possibly even a _SMALL_ ASIC with register files not RAM to facilitate more direct driving of LEDs.

This level of bit stuffing makes the program overheads of sorting out what is where, horrendous and more difficult to follow. Simpler arrays or even arrays of Red and Green LED settings would only be 12 bytes for two arrays of=20

=09Byte of seven bits for a row (of ONE colour LED) =096 bytes gives the 6 rows

This array is internal to the game logic and portable across many=20 platforms. As it only uses 7 bits will work if char is by default signed or unsigned.

Empty or used positions are determined by simple OR logic. Simple AND function determines an error of both arrays cannot have same bit set.

Whatever method is used finding adjacent four bits in any direction needs work. However an array of individual colours/players is easier to scan (Software or Hardware).

If array was transposed to be=20

=09Byte of 6 bits for a column (of one colour LED) =097 bytes gives the seven columns

Other tricks can be employed by using a shifting pattern OR then AND, repeat for easy masking with existing array for simulating by LEDs the counter falling into the column.

Checks for four adjacent values in a byte is a loop with a shifted AND mask and compare. The SAME masks get used for EACH player onto different arrays.

All of this is I/O INDEPENDENT.

All of this keeps things portable, understandable maintainable for the game play.

Note that the maximum in use is 14 bytes, not a lot=20 more than some of the touted methods of 11, 12 or less=20 bytes. So the data storage reduction for the 'portable' section of the code offered, adds a lot of overhead for very little gain, if anything=20 a BIG loss.

If this was then done in hardware by multiplexing the=20 LEDs I would then multiplex the LEDs by reading as=20 wide as possible either the Red array then the Green array, or both Red and Green at same column or row. This way you can incorporate a simple startup "Lamp Test" by having the ability to fill both arrays with

1's to multiplex all LEDs, or with time delays=20 rows or columns at a time.

Tomas could do well to get hold of the book "Front Panel" which discusses things like Model View and Controller to observe how others do things efficiently.

--=20 Paul Carpenter | snipped-for-privacy@pcserviceselectronics.co.uk PC Services Timing Diagram Font GNU H8 - compiler & Renesas H8/H8S/H8 Tiny For those web sites you hate

Reply to
Paul Carpenter

Tomás Ó hÉilidhe schrieb:

True.. Absolutely right. If you can save 10 cent per device you're the hero. No argument against that.

However the point is, that you don't build 17 million devices. You've build a connect-four game with one µC before and you have cross-compiled the same code on your pc.

Those guys who got into the position to decide what µC to use for such bulk-jobs *know* what they're doing because they have many years of experience behind their belt.

Mate, I don't want to depress you. There's nothing bad in knowing the C-standard after 6 years and beeing a good programmer and all, but experience is just what it is: Experience.

You can't replace by having read a book or two. Or beeing the best in your class. Neither you can't win a c-standard flame-war here. Honestly, even if you're prepared it's a fight you cannot win (have you even googled against the names whom you've discussed here? You might be surprised).

I don't thing noone has bad feelings about you. Relax, chill down and take it easy.

Nils

Btw - something for you to think about: I suggest you do a ego-google search on your own name once in a while and read what the first two pages tell other people about you. That's exactly what employers and contractors do these days before they invite for interviews. Beeing easy and nice and willing to lern from the old farts is fine. Arguing against them just for the sake and fun of it is not... (said the main who's ego-google history ain't that clean either.. I do like a good flamewar!)

Reply to
Nils

I think you just made my point for me.

If you've only worked with one processor and one tool chain, then you have absolutely no clue of what it takes to write portable code. You may have loads of book learning, but until you've scraped your knees on at least a half a dozen processors you simply don't have the experience needed to write code that's portable in the real world.

Trust me, after you've tried writing 'portable' code that'll work across half a dozen processors you'll realize just how embarrassed you should be to even _think_ of claiming to write portable code when you've only written code for one processor (and I bet on only one tool chain, for that matter).

--
Tim Wescott
Wescott Design Services
 Click to see the full signature
Reply to
Tim Wescott

The problem with that argument is that you're clearly in a situation where the cheaper micro you have _cannot_ do the job just as well. A bigger micro would do the job a whole lot better than a small micro jumping through all those hoops you're discussing.

That's actually just about the *only* value there is in those games.

Reply to
Hans-Bernhard Bröker

Why?

For a game at this level I would use TWO buttons

=09SHIFT=09Cycle through columns lighting or flashing the TOP most =09=09LED of the right colour in the next available column. =09=09Cycle back to beginning.

=09SELECT Go in that column =20

h

You could just multiplex and even an external decoder for column muxing. This could be used for switch muxing as well.

=097 columns of Red =097 Columns of Green

Oh look 14 decodes, or 14 shifts of a column driving of 6 outputs. Careful timing makes it possible to turn the outputs all off just before a column change, avoid decode glitches. Reading back a common switch line would enable upto 14 switches to be read!

The 6 outputs could still be done by a shift register, and using things=20 like 74HC595 and monitoring the overflow output would enable all sorts of pin reduction.

I think you are making things complicated, unnecessarily.

--=20 Paul Carpenter | snipped-for-privacy@pcserviceselectronics.co.uk PC Services Timing Diagram Font GNU H8 - compiler & Renesas H8/H8S/H8 Tiny For those web sites you hate

Reply to
Paul Carpenter

Hans-Bernhard Bröker schrieb:

Be easy with him. That's a damn good opportunity to learn a lot of things!

Not beeing forced to come up with the most obvious or cheapest solution but to think a bit out of the box is a luxury that only students (and sometimes the R&D-guys as well) have.

Nils

Reply to
Nils

Tim, He is young, eager, a bit naive. How I wish for those days again, but with newsgroups.......

( Just hit 60 in march )

martin

Reply to
Martin Griffith

11 =3D

I don't know what you're getting at here, but the reason I chose to use 00 and 11 for valid values was so that I could do SetAllBitsZero and SetAllBitsOne.

What assumption? Please be specific.

No, it doesn't. The chunk size is determined by BITS_PER_CHUNK. The type, uint8_fast_t, can indeed store values outside the "chunk value range" but that doesn't mean you should try to store 467 in a 2-Bit number. If you compile the program in debug mode, there will be an assertion failure to let you know that 467 is outside the range.

This is now different from trying to store 300 in an unsigned char.

.

I went with uint_fast16_t because I thought 65536 bits was enough. Of course if you want 4 million bits you can always move forward to 32- Bit.

You're confusing things. A macro is a self-contained, self-sufficient entity. If I have a macro called QUANTITY_CHUNKS, then it should be able to be used on its own without parentheses. If it needs parentheses, then it is ill-formed. That is to say, the following is dodgy:

#define BITS_PER_CHUNK 2+3

And it should have been written as:

#define BITS_PER_CHUNK (2+3)

If this wasn't how things worked then you'd see parenthese EVERYWHERE littered throughout code wherever a macro is used.

It overflows, you're right. Integer types don't have infinite range in C. I consciously chose uint_fast16_t because I consciously chose a limit of 65536 bits.

You won't have a 17-Bit chunk. I could use plenty of #error directives thoughout the code to make sure it's not misused.

The main usage would be for BITS_PER_CHUNK > I've written this post to show an example of fully-portable code, that

OK so I'll add a few #error directives to protect it from espionage.

Reply to
Tomás Ó hÉilidhe

^ | | That "now" should be "no".

Reply to
Tomás Ó hÉilidhe

If so, then why did you state a completely different reason for it, before? You said you used that encoding "To use the least amount of memory possible for each LED".

^^^^^^^^^ Typo. That was supposed to be "violated".

Was it really so hard to read one more line before interjecting? Here it is:

Aha. So you don't even see the problem. You said that of course, I can set the chunk size bigger than 3 bits. I thus choose to set it to 13 bits. Can you see where there's a problem with passing 1234 via a 8-bit function argument?

What you thought is irrelevant. You failed to specify that restriction, and that makes the program an incomplete solution to the problem on some architectures.

Why should _I_ have to do that? You claimed you had written a fully portable program. Why should I have to change it to use it on a bigger problem than you thought it should be used for?

Yet your design leaves it up the *user* of your code to define it. Users should not be trusted with knowing such important rules and adhering to them at all time.

You're betting the well-being of your code on assumptions that you neither documented, nor strengthened the implementation against.

Guess what. That's exactly what you *do* see in macros written by experienced programmers.

It's irrelevant what you were or were not conscious of. Talk is cheap.

The only thing that counts is what the code does if used within the limits you actually specified (basically: none), on a random host platform implementing standard C.

You could do that, sure. But you didn't. You claimed it was full-portable as-is. It's not.

Reply to
Hans-Bernhard Bröker

Dead simple and no overhead at all:

static u8 led_state = 0;

// Position = 0...4 // State of each led = 0,1,2

void set_led_state(u8 position, u8 state) { u8 b = 1; while(position--) b *= 3; led_state += (state - led_state%(3*b)/b)*b; }

u8 get_led_state(u8 position) { u8 b = 1; while(position--) b *= 3; return led_state%(3*b)/b; }

This code makes perfect sense for microcontrollers with MUL and DIV. I let Thomas O'Edison (or whatever is his name) elaborate the portability issues.

Yes, of course. This is a hack just for fun.

Vladimir Vassilevsky DSP and Mixed Signal Design Consultant

formatting link

Reply to
Vladimir Vassilevsky

In message , Tomás Ó hÉilidhe writes

Now you are running counter to most standards and guides for portability and safety.

--
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
\/\/\/\/\ Chris Hills  Staffs  England     /\/\/\/\/
 Click to see the full signature
Reply to
Chris H

Seven push buttons is pushing things a bit much. I assume that you are connecting them such that a button press shorts out a resistor, and the resistors are valued in a 1R, 2R, 4R... arrangement.

2^7 is 128, in other words the value of the smallest resistor is less than 1% of the resistance of the entire network.

Since the most accurate resistors readily available off the shelf are 1% tolerance such a design is at the mercy of the precise values of the resistors used to build it. You may get lucky with the prototype but such behaviour cannot be guaranteed over a production run. The behaviour of such a circuit is essentially unpredictable.

--
Andrew Smallshaw
andrews@sdf.lonestar.org
Reply to
Andrew Smallshaw

Here's the idea I have so far:

formatting link

My A2D is 10-Bit, so its value is in the range 0 thru 1023. I need 8 distinct levels, so I divide that figure by 8 to give 127.

Since a reading of 1023 will correspond to 5 volts, 127 will correspond to 620 mV.

I'm still playing around with other aspects of the project but I'll get onto the button input eventually.

Reply to
Tomás Ó hÉilidhe

Awfully strange how such a comment should come from someone posting on an English-speaking group with a name like "Vladimir Vassilevsky". I mean there's nothing wrong with your name, I'm sure it's perfectly normal in your own country, but I just find it awfully strange that such a comment should come from _you_. I'd say "that's rich coming from you", but then I still think the comment would be worthy of shame if came from a "John Smith".

And this is exactly the kind of rude attitude I'm talking about. I've set out being nothing but courteous to people and yet they respond rudely.

Vladimir, slowly but surely, post by post, you're confirming that you're just a rude, hostile, prick. If this attitude of yours is permanent then I'd appreciate you adding me to your killfile.

Reply to
Tomás Ó hÉilidhe

It's worse than that. This code is written to C89, remember, and so uint_fast16_t and uint_fast8_t are undefined types. He mentioned previously that it is OK since _all_ compilers these days have a stdint.h, part from the ones that don't. So is that remotely portable?

Next, look at the definition of the central array: static char unsigned data[BYTES_NEEDED];

char unsigned? OK, the standards do allow it, but it is a strange way of expressing things and is sufficient to raise an eyebrow for no good reason whatsoever. Spare a thought for the next guy and don't use strange expressions without a reason.

I don't intend to comb through this code in detail, others seem to be making a fine enough job of that already. However, I do notice one thing straight away. This code is _long_. Over 140 lines, although I'll knock a bit off since it appears the newsreader did wrap a few lines. Let's say 120.

That's still about six times the length I'd expect. That is in itself a bad thing - long programs are more difficult to port than short ones. That's is without even considering the temporal and memory footprints of such lengthy code.

--
Andrew Smallshaw
andrews@sdf.lonestar.org
Reply to
Andrew Smallshaw

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.