using 8 byte integers where appropriate
"long long" is particularly inappropriate on an 8 bit architecture.
Use "int" (2 bytes) or "long" (4 bytes) if absolutely necessary.
using 8 byte integers where appropriate
"long long" is particularly inappropriate on an 8 bit architecture.
Use "int" (2 bytes) or "long" (4 bytes) if absolutely necessary.
I think the OP wanted to say 8 bits variables, for a very very quick look up, I can say that all this:
// MODE Constants
const uint8_t N_MODE = 11;
const uint8_t N_MAIN_MODE = 6; // main modes are accessable through Mode mode. (sub modes are not).
const uint8_t N_SUB_MODE = 4;
const uint8_t NORMAL_MODE = 0;
const uint8_t SET_TIME_MODE = 1;
const uint8_t SET_COLOR_MODE = 2;
const uint8_t SET_ALARM_MODE = 3;
const uint8_t SERIAL_MODE = 4;
const uint8_t MODE_MODE = 5;
// Sub Modes (this cannot be accessed though Mode mode selection.)
const uint8_t SECONDS_MODE = 6;
const uint8_t ALARM_MODE = 7;
const uint8_t TEMPERATURE_MODE = 8;
const uint8_t SCROLL_MODE = 9;
const uint8_t COUNTDOWN_MODE = 10;
// Temperature unit constants
const uint8_t DEG_C = 0;
const uint8_t DEG_F = 1;
Could be changed to defines, like this:
N_MODE = 11; becomes
#define N_MODE 11
Could be changed to defines
Does that reduce the compiled size?
I never tried that train of words that is static const bla bla bla, I always use defines, so I know that I'm not using extra ram, and to put something in ram it would need to be located in flash as well, so maybe it does, maybe the gcc is smarter than I think.
I've always used #defines partly because I was certain they didn't use any memory and we had a discussion about this a while back.
Anyway I thought I'd do a quick test
//const int x = 9600;
#define x 9600
void setup() {
Serial.begin(x);
}
void loop() {
}
This produces exactly the same code size either way.
Rob
Graynomad:
I've always used #defines partly because I was certain they didn't use any memory and we had a discussion about this a while back.
Anyway I thought I'd do a quick test//const int x = 9600;
#define x 9600
void setup() {
Serial.begin(x);
}
void loop() {
}
This produces exactly the same code size either way.______ Rob
Yes, same code size, but less memory in RAM.
Think about it, for the GCC to decrease the size in code you'd have to skip instructions. Defining a const variable or a define doesn't make the Serial.begin() instruction go away, does it? And that's what is taking up space in the code memory.
I didn't see anything really obvious.
How big is your font table? You might be able to save some space by going to all upper case and deleting some symbols, but if it's a reasonable implementation that ought to be only about 5 bytes per glyph...
PS: upgrade to a recent version of optiboot and gain back an additional 1.5k of code memory.
Yes the vast majority of that size is library and setup code, but if an extra variable was being created I would expect a difference of 1 or 2. Remember we are looking at the difference between #define and const, the existence or otherwise of Serial shouldn't matter.
AFAIK the value reported by the IDE shows the text + data sections so any normal constants that get created (say a string) will go into the data section and show in the total.
This code
const int x = 9600;
//#define x 9600
int y = 12;
void setup() {
Serial.begin(x);
//pinMode (y, OUTPUT);
}
void loop() {
}
Produces
text data bss dec hex filename
1844 18 160 2022 7e6 output/test.elf
Regardless of whether #define or const is used.
"Serial.begin (9600)" produces the same values as well, so I think it's fair to say that no matter what method you employ the memory used (of any kind) is the same. Whether or not something is created in RAM or flash cannot be determined from this, but the two methods are the same. (Note that "y" has been optimized out.)
If I uncomment the pinMode() line we get
text data bss dec hex filename
2020 20 160 2200 898 output/test.elf
Text has increased as expected because we've brought in another library function, but data has risen by 2, ie the size of the int y.
Therefore I submit that "#define", "const" and a literal number all create nothing in RAM (and presumably all create 2 bytes in flash as part of an LDI instruction somewhere) and are essentially the same in this respect.
Rob
It was proven that it is not.
I may be wrong, but I think the define is a compiler directive and not something that gets passed on to the microcontroller... that being said, if you #define something, when you compile, the compiler changes the #define'd for the value used by us. In other words, a define exists merely to allow us to give meaning to values in code. Using const int, would create an actual variable. I know that in the end, it doesn't matter, because both work... but that's what I learned.
One thing that may be happening is the compiler optimization settings equaling a define and a const int to the same. This is after all a memory constrained device and I don't know what optimization options the microcontroller allows or is set to.
Here's a few more discussions on the subject that point out some differences:
http://www.velocityreviews.com/forums/t283393-define-versus-const.html
http://www.gamedev.net/topic/418410-c-difference-between-define-and-const-int/
The reason why the Serial.begin(9600) takes up the same space is because it still needs to load a value (this time from Flash) into memory to pass it on to the register.
But either of them won't solve your memory program shortage. It would be nice though, to create a tutorial or a sticky post explaining this in the forum...
I may be wrong, but I think the define is a compiler directive and not something that gets passed on to the microcontroller...
Pretty much, actually it's a preprocessor thing, it doesn't even get to the compiler.
Using const int, would create an actual variable.
It seems that's not the case.
I confess I put forward almost the same argument as you did not that long ago, I can only assume that the compiler (or optimizer) is clever enough to realize what's going on and it inserts a literal. So effectively the #define and const do the same thing, just in different places.
Rob
Using const int, would create an actual variable.
I'd feel better if they were "static const int xxx = a;"
Without the "static", the compiler will (probably) produce variables as well as use constants, and it is only in the link phase that anything discovers that no other modules access the variables and they therefore can be "garbage collected."
You should be able to see the difference by disassembling the .o files as well as the .elf files.
Can someone try this?
const int x = 9600;
int *ptr;
//#define x 9600
void setup() {
ptr = &x;
Serial.begin(*ptr);
}
void loop() {
}
What I'm trying to prove is that this will create the actual "const int" variable. Of course that the code will be bigger, but the memory footprint will include the const int variable because now there is pointer to it. (Yes, I'm assuming the compiler is not that smart)
Just looks like a very long program to me, around 2,000 lines.
I had a program (several files compared with your one file), that grew to 2,700 lines and took 27K FLASH. It had lots of strings for LCD but I bet the difference between mine and your program is includes. I didn't have that many includes.
Two suggestions I can think off:
This can get significant with Serial.print(). Say you're already using the awesome sprintf, you should NOT use serial.print(int or float or long), only use serial.print(string). Use sprintf to construct a string and print with serial.print(string). Try serial.print(string) and serial.print(float) in one program and get rid of serial.print(float)
void setup()
{
Serial.begin(9600);
}
void loop()
{
Serial.print("3.14");
// Serial.print(3.14);
}
This above program is only 1,894 on my 2009 and 3,726 if I uncomment the second line in loop!!!
liudr:
- USE a 24LC512 EEPROM to store your English letters. Hope this won't slow you down too much. You'll have to try.
I don't see what you mean by English letters... do you mean strings?
Another possibility is to have commands (a couple of bytes) sent to the PC instead of a describing string. And multiply your floating points to 10 or 100 (depending on the size) and use those on the communication to the PC instead of floating point.
liudr:
2) See if you're overloading any functions. Try not to overload. Say you have a constructor chips(int) and another one chips(long). If you used both, just because you didn't bother to convert long into int, the compiler stores both constructors in FLASH.
Also, great advice.
What's english.h? It's not in your code. I suppose if it's a bunch of letter matrix for your persistent (?) display, you will need these matrix letters.
Thank you everyone for looking over the code. I can verify that replacing all of the
const uint8_t bla = xx;
with
#define bla xx
retained the exact code size.
@westwf The font is pretty large, 8 bytes / char. Most symbols use only 7x7 pixels so I could save 128 bytes there. I had a quick look at the optiboot. Looks like the way to go.
Thanks again!
Justin
Can someone try this?
Code:
const int x = 9600;
int *ptr;
//#define x 9600void setup() {
ptr = &x;
Serial.begin(*ptr);
}void loop() {
}
That doesn't compile which implies to me that the compiler knows you can't have a pointer to something that won't exist at run time.
Rob
const int x = 9600;
const int *ptr;//#define x 9600
void setup() {
ptr = &x;
Serial.begin(*ptr);
}void loop() {
}
What I remember from the GCC documentation...
"const" only uses storage (SRAM) if it appears in more than only module (source file).
"static const" nevery uses storage.
Except when the address is taken (like the example above) which forces the compiler to place the constant in memory.
In other words, so long as there is not a pointer involved, "#define" and "static const" are identical in terms of storage. "static const" has the distinct advantage of also carrying the data-type.