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 CCS Technical Support

ROM size Not Enough, a lot of NESTED IF/ELSE + SWITCH()

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



Joined: 31 Oct 2007
Posts: 5

View user's profile Send private message

ROM size Not Enough, a lot of NESTED IF/ELSE + SWITCH()
PostPosted: Wed Nov 21, 2007 12:39 am     Reply with quote

Version: CCS PCM C COMPILER, version 4.033, 33187

PIC: 16F690

Background:
Wanted to build a program which can verify various instructions input through RS232. IF verification is correct, 16F690 will act as slave and send data to the master. IF input is wrong, the phrase ERR will pop up to notify user instantly. IF input is correct, an OK phrase will appear (perform sending instruction). There are about 80 sets of instructions, all with 8 characters.

For example:

"POWR0 " (3 blank space behind)
"CLCK*** " (1 blank)
"CHUP "(4 blank space)
"CHDW " (4 blankspace)..

If the user type X for the first word, the program will pop up ERR, as there is no instructions starts with the word X. Even if he type P->X, the ERR will pop up instant too.
The phrase OK will come out if and only if the user enter the codes in the correctly.


Of course,these are only 4 examples.. there are still whole load of nested if else and switch case inside..

I don't know how to separate this to two functions as i saw in other threads separating 1 big function into 2 functions may solve the problem.

So being a newbie, i did sth like below:

Code:


#include <16F690.h>
#use delay(CLOCK=18432000) // using a 18.432Mhz clock
#use rs232(baud=9600, XMIT= PIN_B7, RCV= PIN_B5) // rs232 setting
#fuses HS,NOWDT,NOMCLR,NOPROTECT,NOBROWNOUT,NOFCMEN,NOIESO,NOCPD,NOPUT

/* Use internal clock mode, no watch dog, no code protect, no powerup timer */


char ch;


void ioput()
{
putc(ch);
ch=getchar();
}
void putsOK()
{
putc(ch);
putc('O');
putc('K');
putc('\n');
putc('\r');

}

void putsERR()
{
putc('E');
putc('R');
putc('R');
putc('\n');
putc('\r');
}


void checkinput()
{
ch=getchar();
switch(ch)
   {case 'P':
         ioput();
         switch(ch)
         {    case 'O':
                   ioput();
                  if (ch=='W')
                  {   ioput();
                     if(ch=='R')
                     {ioput();
                        if(ch=='0')
                        {ioput();
                           if(ch==' ')
                           {ioput();
                              if(ch==' ')
                              {ioput();
                                 if(ch==' ')
                                 {putc(ch);
                                  putsOK();
                                 //perform action POWR0
                                 }
                       
                                 else putsERR();
                                 }
                     
                             else putsERR();
                              }
                       
                           else putsERR();
                           }
                     
                        else putsERR();
                        }
                 
                     else putsERR();
                     }
               
                  else putsERR();
                  break;

case 'C':
         ioput();
            switch(ch)
            {case 'L':
                   ioput();
                     if(ch=='C')
                     {ioput();
                        if(ch=='K')
                        {ioput();
                           if(ch=='*')
                           {ioput();
                              if(ch=='*')
                              {ioput();
                                 if(ch=='*')
                                 {ioput();
                                    if(ch==' ')
                                    {
                                     //perform CLCK***
                                     putsOK();
                                    }
                                    else putsERR();
                                 }
                                 else putsERR();
                              }
                              else putsERR();
                           }
                           else putsERR();
                        }
                        else putsERR();
                     }
                     else putsERR();
                     break;
                       
               case 'H':
                     ioput();
                     switch(ch)
                     {case 'U':
                           ioput();
                           if(ch=='P')
                           {ioput();
                              if(ch==' ')
                              {ioput();
                                 if(ch==' ')
                                 {ioput();
                                    if(ch==' ')
                                    {ioput();
                                       if(ch==' ')
                                       {
                                        //perform CHUP
                                        putsOK();
                                       }
                                       else putsERR();     
                                    }
                                    else putsERR();   
                                 }
                                 else putsERR();   
                              }
                              else putsERR();
                           }
                           else putsERR();
                           break;
                     
                      case 'D':
                           ioput();
                           if(ch=='W')
                           {ioput();
                              if(ch==' ')
                              {ioput();
                                 if(ch==' ')
                                 {ioput();
                                    if(ch==' ')
                                    {ioput();
                                       if(ch==' ')
                                       {
                                        //perform CHDW
                                        putsOK();
                                       }
                                       else putsERR();     
                                    }
                                    else putsERR();   
                                 }
                                 else putsERR();   
                              }
                              else putsERR();
                           }
                           else putsERR();
                           break;

                     default: putsERR();
                            break;
                     }         
                     break;

               default: putsERR();
                      break;

            }
         break;   

default:putsERR();
          break;
   }

}



void main()

{

while (1)
{

checkinput();
}
}




Sorry for the long code.
The actual 1 is 100x times longer
yesahycs



Joined: 31 Oct 2007
Posts: 5

View user's profile Send private message

more details
PostPosted: Wed Nov 21, 2007 2:05 am     Reply with quote

Code:


ROM used: 1772 (43%)
          1772 (43%) including unused fragments

          1 Average locations per line
          2 Average locations per statement

RAM used: 7 (3%) at main() level
          7 (3%) worst case

Stack used: 2 worst case (out of 8 total available)

Lines Stmts  %   Files
----- ----- ---  -----
 1587   954 100  project.c
  375     0   0  C:\Program Files\PICC\devices\16F690.h
----- -----
 1962   954 Total

Page ROM  %  RAM   Vol Diff  Functions:
---- --- --- ---   --- ----  ----------
0      9   1   0    35  1.6  ioput
0     21   1   0    86  1.3  putsOK
0     21   1   0    86  1.3  putsERR
0   1683  95   0 29854  6.0  checkinput
0     34   2   0    27  1.0  MAIN

Program metrics:
    Functions               5
    Statements              954
    Comments                372
    Volume (V)              30705
    Difficilty (D)          12.9
    Effort to implement (E) 395392
    Time to implement (T)   6 hours, 6 minutes
    Est Delivered Bugs (B)  2
    Cyclomatic Complexity   338
    Maintainability (MI)    61

 Segment     Used  Free
-----------  ----  ----
00000-00003     4  0 
00004-007FF  1768  276 
00800-00FFF     0  2048 
SET



Joined: 15 Nov 2005
Posts: 161
Location: Glasgow, UK

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Wed Nov 21, 2007 4:54 am     Reply with quote

Your code is a classic 'code driven' approach, whereas you need to let the data drive the logic. Something like:

Code:
char ch;

#define CMD_LEN_MAX 8 // or as reqd
#define NO_OF_CMDS 80  // or as reqd

// const is a must so that compiler puts in flash, not RAM
const char commands[NO_OF_CMDS][CMD_LEN_MAX] = {
                  "POWR0",
                  "OtherCmds" }; // etc!

int not_command[NO_OF_CMDS];

void ioput()
{
putc(ch);
ch=getchar();
}
void putsOK()
{
putc(ch);
puts("OK\n\r");
}

void putsERR()
{
puts("ERR\n\r");
}


void checkinput()
{
      int i,j,no_match;

      for(i=0; i<NO_OF_CMDS;i++)
                not_command[i] = 0;

      for(j=0; j<CMD_LEN_MAX; j++) {
     
         ch = getchar();
         no_match = 1;

         for(i=0; i<NO_OF_CMDS;i++) {

               // this command failed to match so ignore                 
               if(not_command[i])
                   continue;

               if (commands[i][j] == ch)
                    no_match = 0;
               else
                    not_command[i] = 1;
         }

         if(no_match) {
              putsERR();
              return;
         }
      }
     putsOK();
}


I've just typed this in pretty quickly so apologies for any errors, but you can see the general idea.
Guest








PostPosted: Wed Nov 21, 2007 6:55 pm     Reply with quote

Thanks.
I'm out of town now, will try it at home.
However i wonder will the ram size fit all the commands..
Its around 100 comands, each command will hold 9 characters (include blanks).
yesahycs



Joined: 31 Oct 2007
Posts: 5

View user's profile Send private message

PostPosted: Wed Nov 21, 2007 11:30 pm     Reply with quote

Hmm, i did not tried the code yet.
After browsing it through, it MAY verify the input.
However, after verifying the input, i need to send the input as SLAVE thru I2c to the master.
According to SET's code, the program only puts OK and cannot send different instructions for diff inputs.

correct me if i'm wrong.
I'm still a newbie.
SET



Joined: 15 Nov 2005
Posts: 161
Location: Glasgow, UK

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Thu Nov 22, 2007 6:15 am     Reply with quote

Quote:
After browsing it through, it MAY verify the input.
However, after verifying the input, i need to send the input as SLAVE thru I2c to the master.
According to SET's code, the program only puts OK and cannot send different instructions for diff inputs.


To do this, set a variable that is set to a unique value after each command string is recognised. Then call a different function (or perform a different action) depending on this variable.
Ttelmah
Guest







PostPosted: Thu Nov 22, 2007 9:16 am     Reply with quote

To have any hope of doing this, you are going to need to:
1) Learn something about the code and chip....
2) Think _very_ carefully...
Now, '1' applies, because you mention _RAM_. SET's approach, _does not use the RAM_. The strings are declared as 'const', which means they are in _ROM_.
'2' applies, because there _will_ still be problems.
100, 9 character commands, would correspond to 900 characters. With 'null' separators (strings in 'C', have an extra 'null' character at the end of each), which would take the space _just to store the commands_, to 1000 characters. nearly 1/4 the ROM, just to hold the commands, before doing anything at all with these. However you also have the problem that the largest array supported on the 12 family chips is just 256 characters, which means you will _need_ to think things out a lot more.
Some questions apply.
Do the commands fall into 'sets' of different lengths, or types, possibly with similar starting letter combinations for the sets?. If so, then you should be able to save storage. How many different things do you need to do 'with' the commands?. Given the number of possible commands, and the storage available, it may well be impossible to actually achieve in this chip, unless the number of 'outcomes' is not as many as the number of commands.

Best Wishes
SET



Joined: 15 Nov 2005
Posts: 161
Location: Glasgow, UK

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Thu Nov 22, 2007 9:23 am     Reply with quote

I agree with Ttelmah - in some ways this is an ambitious project for a 'newbie'. You need to get more familiar with how the language (C) maps to the actual chip, it's memory sizes and structure. We all have to do this to some extent - right now I'm doing some DSP work on TI chips, in some ways much the same, but with differences too (code can execute out of RAM or Flash for example).
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