So I Googled for that error message and found a few things of interest:
HI-TECH Software Frequently Asked Questions
HI-TECH Software Forums: error in MPLAB
HI-TECH Software Forums: Error [1347] ; 0. can't find 0x1 words (0x1 withtotal) for psect
Read through those. One suggests the printf family of functions may be the culprit. More on optimizing that later.
My first suggestion would be to look at compiler settings. Embedded compilers usually let you specify code, data, stack and heap sizes, so maybe you could adjust that.
You also have a few quirks in your code. First, you're putting an extra null character at the end of some of your sprintf commands (sprintf puts a null for you). Also, I don't know why you're using goto, you could just put the code below LOCATION1: inside the while loop, like so:
Code:
do {
strcpy(TopMessage, "Input Stride");
sprintf(BotMessage, "%d cm \0", stridelength);
LCDWrite(0b00000001, 0);
for (i = 0; i < Delay; i++);
for (i = 0; TopMessage[i] != 0; i++)
LCDWrite(TopMessage[i], 1);
LCDWrite(0b11000000, 0);
for (i = 0; BotMessage[i] != 0; i++)
LCDWrite(BotMessage[i], 1);
if (UP == 1)
...
} while (FORWARD != 1);
It might help if you get rid of more global variables by moving them into functions so they only exist on the stack when the function is active (i, j, k, n, TopMessage and BottomMessage). You could also try making your const ints for your delay loop #defines instead. This means they will be worked into the assembly instructions in immediate mode if possible instead of having to read the data from memory in one instruction then use it in a second.
Also, a good practice in general (not just for shrinking code) is to find any section of repeated code and turn it into a function. That might not work for every case because if you have only 2 simple lines of code repeated, the overhead of a function call may make your code bigger. One obvious instance of this I see is the code for writing TopMessage and BotMessage to the screen. Put the following into a function, and try passing in TopMessage and BotMessage (after making them local to main):
Code:
LCDWrite(0b00000001, 0);
for (i = 0; i < Delay; i++);
for (i = 0; TopMessage[i] != 0; i++)
LCDWrite(TopMessage[i], 1);
LCDWrite(0b11000000, 0);
for (i = 0; BotMessage[i] != 0; i++)
LCDWrite(BotMessage[i], 1);
The last thing is something I actually suggested early on, making an array out of the display screens, with a top message, bottom message/format string, and address of data to print, then you can eliminate your switch statement and have just one instance of the code to print a particular screen, like so (this is untested, but gives you the idea):
Code:
struct screen {
char *top;
char *bot;
int *data
} screen_data[NUM_SCREENS] = {
{"You have taken", "%d steps", &noofsteps},
...
};
...
while (1) {
...
// these two lines replace your entire switch statement
sprintf(buf, screen_data[menulevel].bot, *(screen_data[menu_level].data));
output_message(screen_data[menulevel].top, buf); // this is the function I had you make above.
}
I was going to mention writing your own "printf" type routine, but I wouldn't worry about that yet. The 3 code changes I would make are the output_message function, dropping the switch statement in main and removing global variables.