My project is finished (for the present)
This is a new Moving Message Display with a LPC2138 and 8(16) x 5x7 led matrix, working.
It uses a new and fast algorithm, written in C.
It is modular: it uses one or two same 8 char display unit(s).
Online commands (via rs232, in Virtual Terminal)
- scrolling by pixel or by character or by graphic - pause/continue scrolling - on/off one pixel gap between fonts - home function (back to the begin) - max. 127 chars displayable text - - - stored in the memory - scrolling speed up/down - single step left/right - ASCII char test - multi language characters (also full American) - default settings via switches - get/store settings from/to memory
Latest addition
- - - last typed char is deletable (backspace function), this was very difficult to code.
I'm going to attach here the two projects (for 8 and 16 chars) with the hex firmware only, beacuse I wrote the program in C but with many (70%) hard and hand optimalisation in C (for the speed). It is not a human readable program, sorry...
Please study also my next posts at this thread if you want to build this!
Try it!
About the source look at my next posts here!
You are correct.
When you recieve the source code and you see tomorrow you will be pleased with joy. It is very fast.
I don't really remember the last time I used the register keyword. But I'm pretty sure it was with Turbo C or Borland C. And it was two-digit years ago.
This is a keyword that should be removed from the standard. I think quite a number of compilers are ignoring it. An old 8080 or 8086 had very few registers while at the same time you had extremely little memory available for the code analyzer.
A modern compiler can basically try every single combination of register/not register for the variables and compute what is best. It can compute the lifetime of the variables, allowing multiple variables to be stored in the same register at different sections of a function. And a variable can change from being stored on the stack to being stored in a register - or the reverse - for different sections of the code.
With a modern compiler (who do honor the register keyword, if such compilers exists), forcing a specific variable into a register is almost guaranteed to reduce the efficiency of the code.
Another thing - moving specific variables to registers is something that basically requires you to adapt your source code to the generated assembler code. But the code generation depends on compiler version, optimization settings etc. So the only times when it is really important to force a variable into a register you should instead use assembler. That is the only way you will know what the code looks like and the full implication of having a variable in a register.
When writing C code - avoid situations where the compiler needs to perform multiplications to index arrays (unless the processor has such multiplication supported in hardware - for example automagically scale an index with 4 to handle an array of 4-byte entries.
It is normally better to write:
p_end = data + 100; p = data; while (p < p_end) port = *p++;
than to write:
for (i = 0; i < 100; i++) port = data[i];
The first alternative have two variables in the loop - one a constant and one with auto-increment.
The second alternative needs i and data as variables but needs also the numeric constant 100 for the comparison. And if sizeof(data[0]) isn't a size the processor can directly compute the address for, then data[i] may have to be rewritten by the compiler as:
port = *(element*)((unsigned char*)data + i*element_size)
and the i*element_size part can be expensive.
Having multi-dimensional arrays will quickly consume new registers while possibly add a lot of computations to figure out the offset of the [i][j][k]... th element.
You must wait for tomorrow and the source code will be on the web page.
The standard has always defined this as only a hint to the compiler - compilers have never had to take any notice of it!
The ARCC Manual is unhelpful on the subject:
"Using the ARM compiler, you can declare any number of local objects to have the storage class register." www.keil.com/.../armccref_chddfaec.htm
Which tells you nohing as to what effect (if any) declaring an object as 'register' may have...
:-(
(but, given that the total number of registers is limited, one can conclude that it must sometimes have no effect...)
Not true. They've always been required to disallow taking the address of such variables:
The operand of the unary & operator shall be either a function designator, the result of a [] or unary * operator, or an lvalue that designates an object that is not a bit-field and is not declared with the register storage-class specifier
[C99 6.5.3.2 paragraph 1, emphasis mine]
And since defining arrays with storage class register causes undefined behaviour, you can't get around this by passing the name of an array, either.
That cannot be all it says about register. The compiler documentation is required (by the C standard, C99 6.7.1 paragrahp 4) to specify the "extent of effectivenes" in its documentation. "Implementation-defined" means the implementation is required to define it, in the documentation.
defining arrays with storage class register causes undefined behaviour,
Ooops, that was an incorrect interpretation. It's using the name of a register-class array as an implied pointer to its first element that causes undefined behaviour, not defining such an array. OTOH, since that and 6.5.3.2 basically kill all useful things one can do with an array, there's no point defining one.
That is the entire content of the Home » Standard C Implementation Definition » Implementation definition » Registers section of the RealView Compiler Reference Guide
"The compiler documentation is required to specify the 'extent of effectivenes' in its documentation"
The difficulty of finding anything in the Keil/ARM documentation has been noted on several occasions...
Some you said is correct and some is incorrect.
You will learn much from the code.
Soon.