CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Text Based Menus

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

Text Based Menus
PostPosted: Wed Sep 15, 2010 10:15 am     Reply with quote

Hello all,

I am developing a data logger and I want to present the setup functions
of the logger in a text based menu on hyperterminal.

Such menu should have options to set the time of the onboard RTC. The Measurment interval, and Dumping/erasing data from the onboard EEPROM... all this needs to be displayed properly formated and as clear as possible....and simple too...

For example something like this would suffice:

*****************MENU*************
*
* a) set time
* b) Dump Data
* c) Erase Data
* d) set Interval
*
***********************************

Every time it goes into an option another similar submenu is displayed - or the option is direcly executed....

The hyperterminal text box should only display the current menu / option.... not a new menu under the old one.... part of my question I guess is how to clear hyperterminal...I don't want to see the history of what has been previously displayed.

My question is purely on the display issues...

Has anybody coded a menu as such before?
Can you direct me to the nearest post on this issue?
my_search = Return(0x00);
Do you have any suggestions as to how could I do this without eating all my rom with printf()s and stored characters? An efficient printing loop?
I'm not looking for you to code this for me.....

Also, to see what I type/send to the PIC, should I echo from my ISR or once I exit the ISR? Or is the hyperterminal echo option a good choice?
I kinda know the answer to this... but I figured it can't help to ask.

You may wonder why hyperterminal? its common...

Sorry for the long post...

I'd appreciate any help...



gabriel.
_________________
CCS PCM 5.078 & CCS PCH 5.093
ECACE



Joined: 24 Jul 2006
Posts: 94

View user's profile Send private message

PostPosted: Wed Sep 15, 2010 11:51 am     Reply with quote

Per the Microsoft website, you can not clear the Hyperterminal screen.

http://support.microsoft.com/kb/123988

I had to do a similar type menu (For the same reason), and had to just do a bunch of line feeds.

Though it is not real clean code...it works though, this is how I did my menu. And as for using up memory, I wish there was a better way, but I don't know of one. One thing you could do is set up a loop to repeatdly put out the line feed instead of manually the way it is in my code below.

I have the first case statement, but you get the idea of what I was doing.

Code:

      While(1)
      {
         DisplayMenu();
         ProcessMenu();
      }
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//             Display Menu                                                   //
////////////////////////////////////////////////////////////////////////////////
void DisplayMenu()
{

int i;                                                  //Used in the COMMAND_TEMP conversion

printf("\r\n\r\n\r\n");                        //Place a bunch of lines between 1 run and another
printf("Stepper motor controller ---\n\r\n\r");
printf("HT   -- Holding Tq (1-10)\n\r");
printf("RT   -- Running Tq (1-30)\n\r");
printf("DFT  -- Default Tq (HT = 1 + RT = 10)\n\r");
printf("SPD  -- Speed (RPM)(1-10K)\n\r");
printf("SPR  -- Steps/Rev of motor  (1-1K)\n\r\n\r");

printf("FWx  -- FWD x steps(1-400)\r\n");
printf("RVx  -- RVS x steps(1-400)\r\n");

printf("REVF -- FWD x revs (1-1K)\r\n");
printf("REVR -- RVS x revs (1-1K)\r\n\r\n");

printf("MD     -- 1 = Full Step 2 Phase\r\n\t  2 = 1\\2 Step\r\n\t  3 = Full Step\r\n\r\n");

printf("STS    -- Status\r\n\r\n");

printf("Enter command and press <ENTER>\r\n");        //Get command and attributes in string
gets(COMMAND);

   for(i = 0 ; i <= 4 ; i++ )                         //Convert COMMAND_TEMP to all uppercase
      {
         COMMAND[i] = toupper(COMMAND[i]);
      }
     

printf("Attributes? <ENTER>\r\n");         //Get command and attributes in string
gets(ATTRIB);

}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//             Process Menu                                                   //
////////////////////////////////////////////////////////////////////////////////
void ProcessMenu()
{
/*
   HT,               //Holding Torque adjustment
   RT,               //Running Torque adjustment
   DFT,              //Loads both default torques
   SPD,              //Loads the user speed
   FWx,              //Forward x # of steps
   RVx,              //Reverse x # of steps
   REVF,             //Forward x # of Revolutions
   REVR,             //Reverse x # of Revolutions
   MD,          //Mode, sets 1/2 step, full step, or 2 phase full step
   STS,          //Status -- Gives back all of the parameters above
   SPR,          //Steps Per Revolution -- Allows user to set how many steps the stepper motor has

*/

     if ((strcmp("HT", COMMAND)) == 0 )
         cmd = 1;
         
else if ((strcmp("RT", COMMAND)) == 0 )
         cmd = 2;

else if ((strcmp("DFT", COMMAND)) == 0)
         cmd = 3;
   
else if ((strcmp("SPD", COMMAND)) == 0)
         cmd = 4;
         
else if ((strcmp("FWX", COMMAND)) == 0)
         cmd = 5;
   
else if ((strcmp("RVX", COMMAND)) == 0)
         cmd = 6;
   
else if ((strcmp("REVF", COMMAND)) == 0)
         cmd = 7;
   
else if ((strcmp("REVR", COMMAND)) == 0)
         cmd = 8;
   
else if ((strcmp("MD", COMMAND)) == 0)
         cmd = 9;
         
else if ((strcmp("STS", COMMAND)) == 0)
         cmd = 10;
         
else if ((strcmp("SPR", COMMAND)) == 0)
         cmd = 11;
                 
else
   cmd = 12;

// Now that all commands have been assigned an int #, we can control
// it with a switch statement below, but first we need to convert the
// ascii ATTRIBUTES to an integer

attribs32   =  atoi32(ATTRIB);                              //Convert ascii to integer + gives attribs 32
attribs8    =  make8(attribs32,0);                          //Strip off lower 8 bits to make attribs 8
attribsupper = make8(attribs32,1);                          //Strip off upper 8 bits of attrib 16
attribs16   =  make16(attribsupper,attribs8);               //Converted value of 16 bit attribs

switch(cmd)
   {
///////////////////DONE////////////////////////////////////////////////////////     
      case(1):                                              //Sets the Holding Torque level
      {
      HLD_TQ = attribs8;                                    //Apply attribs to Holding Torque
                                                            //Takes just the lowest byte
      if (HLD_TQ > HLD_TQ_LIMIT)                  //If attempted level is > than the Holding
         HLD_TQ = HLD_TQ_LIMIT;                             //limit, then it is set to the
         
      set_pwm1_duty(HLD_TQ);                                //Now set the Holding Torque Level
      }   
      break;                                                //Holding Torque Limit

_________________
A HW Engineer 'trying' to do SW !!! Run!!!
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

PostPosted: Wed Sep 15, 2010 12:26 pm     Reply with quote

Hello ECACE,

Thanks for your reply.

i particularly like the use of the Gets() function... i had not thought of this... that solves one of my problems THANK YOU.
i was caught up inside my "box".... would have never remembered to use that....

now that raises another question which you might be able to answer..
i have never really used gets... will try tonight though!

i understand that Gets() saves the incoming chars into a string.
it exits once a return or new line is encountered....

now, my input is "time"... so i expect 2 chars before the \r.
for minutes, hours, etc...
what if by some reason the user inputs 3 chars before the \r?
typos do ocurr while trying to set up any machine...

does the string loop back? (circular buffer style)....i guess i could implement a check after the gets() call...

basically my question is how do you handle wrong inputs?

my original idea was:

Code:
prompt user for input
wait for incoming character
ISR fires + sets flag
check char to be limit1>char<limit2 (or some variation of this)
if check passed, continue to next char
else warn user
reset input string
request for new input
repeat till good.

on to next input field




i guess that would be writing my custom Gets function.....thoughts?

i see for printing you do what i had hoped to avoid....alot of printfs
i guess simple is better.... or mabey faster?
i am willing to sacrifice space for speed.

i see you print to the user the expected values.... Good idea.
i shall do the same...



Regarding clearing hyperterminal:

Quote:
Try using Ctrl-L (0x0C). This may only work in TTY mode.
Otherwise, the ANSI sequence for clear screen is:
ESC, "[2J"



i found this today..... on a microchip forum....

ill try this tonight aswell
any thoughts?



thank you for your time..

g
_________________
CCS PCM 5.078 & CCS PCH 5.093
ECACE



Joined: 24 Jul 2006
Posts: 94

View user's profile Send private message

PostPosted: Wed Sep 15, 2010 12:36 pm     Reply with quote

I have defined the variables up front for the maximum size expected and gave the user the expected ranges. So if they were to put in a value that was too high, it would fail. For example if they were to put in 10,000 for the requested torque, it would only get the lower part of it as I only use the lower 8 bits.

If you go over the amount alloted, I think it only takes the first 5 chars for example in COMMAND.

Code:

char                    COMMAND[5];                   //Holds ascii response from user in menu
char                    ATTRIB[4];                    //Holds ascii response from user in menu
static unsigned int     cmd;                          //Becomes the integer equivalent of the COMMAND
static unsigned int32   attribs32;                    //Becomes the 32 bit integer equivalent of the ATTRIB
static unsigned int16   attribs16;                    //Becomes the 16 bit integer equivalent of the ATTRIB
static unsigned int8    attribs8;                     //Becomes the 8 bit integer equivalent of the ATTRIB
static unsigned int8    attribsupper;                 //Temp register to hold upper byte of attribs16 for conversion


I am not using interputs for the communications, so I just sit there till the user hits enter.
_________________
A HW Engineer 'trying' to do SW !!! Run!!!
John Morley



Joined: 09 Aug 2004
Posts: 97

View user's profile Send private message

PostPosted: Wed Sep 15, 2010 6:57 pm     Reply with quote

Hi,

Far be it from me to contradict Microsoft, but.....

If you use this code, you can clear the HyperTerminal display.....

Code:

//Here we clear the HyperTerminal display screen   
   printf("\x1B[2J");



John
_________________
John Morley
Jerson



Joined: 31 Jul 2009
Posts: 122
Location: Bombay, India

View user's profile Send private message Visit poster's website

PostPosted: Wed Sep 15, 2010 7:02 pm     Reply with quote

John, you are right when Hyperterm is set to VT100 emulation. That sequence does not work otherwise.
ECACE



Joined: 24 Jul 2006
Posts: 94

View user's profile Send private message

PostPosted: Wed Sep 15, 2010 7:19 pm     Reply with quote

John,

Very cool. I was unaware about setting it to VT100. Thanks for the info.
_________________
A HW Engineer 'trying' to do SW !!! Run!!!
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Wed Sep 15, 2010 9:45 pm     Reply with quote

yea, I have a whole VT100 based menu system on one project that's in color (on hyperterminal) and uses

Code:
void cls ( void ) {
   fputc(27, COMM);
   fputc('[', COMM);
   fputc('2', COMM);
   fputc('J', COMM);
   fputc(27, COMM);   // VT100 Home Cursor
   fputc('[', COMM);
   fputc('H', COMM);
}

_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
Wayne_



Joined: 10 Oct 2007
Posts: 681

View user's profile Send private message

PostPosted: Thu Sep 16, 2010 2:02 am     Reply with quote

ECACE wrote:
I have defined the variables up front for the maximum size expected and gave the user the expected ranges. So if they were to put in a value that was too high, it would fail. For example if they were to put in 10,000 for the requested torque, it would only get the lower part of it as I only use the lower 8 bits.

If you go over the amount alloted, I think it only takes the first 5 chars for example in COMMAND.

Code:

char                    COMMAND[5];                   //Holds ascii response from user in menu
char                    ATTRIB[4];                    //Holds ascii response from user in menu
static unsigned int     cmd;                          //Becomes the integer equivalent of the COMMAND
static unsigned int32   attribs32;                    //Becomes the 32 bit integer equivalent of the ATTRIB
static unsigned int16   attribs16;                    //Becomes the 16 bit integer equivalent of the ATTRIB
static unsigned int8    attribs8;                     //Becomes the 8 bit integer equivalent of the ATTRIB
static unsigned int8    attribsupper;                 //Temp register to hold upper byte of attribs16 for conversion


I am not using interputs for the communications, so I just sit there till the user hits enter.


It is worse than this.
Code:
 
char COMMAND[5];

Can hold 5 characters BUT the fith will allways be null, 0x00, '\0', 0 for a string, which is the string termination character, so you can only use 4 for your command or number!
IF you go over the 4 + null then you will overwrite the data in memory that follows this buffer, corrupting some other data or register depending on where the compiler puts your buffer!
gets does NOT know how big your buffer is so will just continue to overwrite data as more chars are entered.
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

PostPosted: Thu Sep 16, 2010 6:28 am     Reply with quote

hi all,

i tried Gets() last night...

it didnt work with my code.... now... i think i figured out the answer on my way to work....

i have a size 4 array set as RS232 circular buffer...
the array loops back on the 3 item. ....

i use gets to receive 2 chars then <ENTER>.... i forgot that it also adds a 0 for the string termination... so i think that my problem could be any of the following...


so if i expect 2 values my string should hold 4 characters?

does Gets start filling up the array you provide it starting at position 0?
what if the target string already has \r from a previous run?
i know it stops when it gets 0x13... but does it actually store the 0x13 in the string?

if my input is '1' '5'

my string is "15\r0" ?


g
_________________
CCS PCM 5.078 & CCS PCH 5.093
ECACE



Joined: 24 Jul 2006
Posts: 94

View user's profile Send private message

PostPosted: Thu Sep 16, 2010 6:39 am     Reply with quote

Wayne - Correct, the last char would be the null, so only the 4 would be accepted for command. Hence the last case is if the command did not match one of the defined ones listed in the menu.

Is this the most ideal way to do it? Probably not, but for an engineering tool (Which is what this was...stepper motor controller for motor qualifications), this worked fine. The user being an engineer who would enter the parameters.

Now exaclty what the compiler does with the others, is unknown to me. I did a test where I just held a key down and entered over a hundred chars, just to see what happened, it did not cause a crash. I would be curious to know what it does with the others.


Wayne_ wrote:
ECACE wrote:
I have defined the variables up front for the maximum size expected and gave the user the expected ranges. So if they were to put in a value that was too high, it would fail. For example if they were to put in 10,000 for the requested torque, it would only get the lower part of it as I only use the lower 8 bits.

If you go over the amount alloted, I think it only takes the first 5 chars for example in COMMAND.

Code:

char                    COMMAND[5];                   //Holds ascii response from user in menu
char                    ATTRIB[4];                    //Holds ascii response from user in menu
static unsigned int     cmd;                          //Becomes the integer equivalent of the COMMAND
static unsigned int32   attribs32;                    //Becomes the 32 bit integer equivalent of the ATTRIB
static unsigned int16   attribs16;                    //Becomes the 16 bit integer equivalent of the ATTRIB
static unsigned int8    attribs8;                     //Becomes the 8 bit integer equivalent of the ATTRIB
static unsigned int8    attribsupper;                 //Temp register to hold upper byte of attribs16 for conversion


I am not using interputs for the communications, so I just sit there till the user hits enter.


It is worse than this.
Code:
 
char COMMAND[5];

Can hold 5 characters BUT the fith will allways be null, 0x00, '\0', 0 for a string, which is the string termination character, so you can only use 4 for your command or number!
IF you go over the 4 + null then you will overwrite the data in memory that follows this buffer, corrupting some other data or register depending on where the compiler puts your buffer!
gets does NOT know how big your buffer is so will just continue to overwrite data as more chars are entered.

_________________
A HW Engineer 'trying' to do SW !!! Run!!!
Wayne_



Joined: 10 Oct 2007
Posts: 681

View user's profile Send private message

PostPosted: Thu Sep 16, 2010 7:05 am     Reply with quote

ECACE wrote:
Now exaclty what the compiler does with the others, is unknown to me. I did a test where I just held a key down and entered over a hundred chars, just to see what happened, it did not cause a crash. I would be curious to know what it does with the others.


The compiler itself does not do anything with the chars it just creates the code (program) that you run on the pic. What the program does, when using gets is it starts to write chars in the buffer you gave it BUT it doesn't know anything about the buffer except for the address of the first location you want to start saving the data.

What I mean by thi is, if you pass an array name
Code:

char buf[10];
gets(buf);

It will start filling the memory at the address where buf starts, you can change the start point by:-
Code:

char buf[10];
gets(&buf[5]);

But the routine does not know you are starting at position 5 or that there are only 5 spaces available.

Also, gets will not store the <cr> (return, char(13), 0x0D) char but replace it with the null.

The fact that your code did not fall over when you entered over 100 chars is because of the location of your array (in respect to other vars) or the usage of other vars that may have become corrupted in your code!
If you only have the one buffer and all other vars are created prior to this then a buffer overwrite will not affect any other vars, Also if you code does not then use any overwritten data in it's functionality you will not notice any corruption or experiance a crash.

With computer programming this is not as straight forward because your code is stored in ram so there is a possibility of code corruption as well as data corruption, also where stacks are used for storing data.

You were just lucky in your test routine. Mabey not so lucky if you tried the same test with you propper code?

Anyway, you need to be aware of possible consiquencies of using gets! mainly because you can not always control what a user will enter.
ECACE



Joined: 24 Jul 2006
Posts: 94

View user's profile Send private message

PostPosted: Thu Sep 16, 2010 7:19 am     Reply with quote

Thanks for the detailed info.
_________________
A HW Engineer 'trying' to do SW !!! Run!!!
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group