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

Help optimizing code for LED scrolling sign
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
williefeb_19



Joined: 21 Apr 2008
Posts: 18

View user's profile Send private message

Help optimizing code for LED scrolling sign
PostPosted: Mon Apr 21, 2008 11:53 pm     Reply with quote

I am new to C programming and I am trying to make a led scrolling sign using a PIC16F690 and MAX6954APL driver connected via an SPI interface. I have 8 14-segment displays hooked up and functioning correctly. I want to know if there is an easier or more efficient way to be able to change messages and make it scroll. What I have works but it isn’t easy to change the message.

In the future want to add the ability to change the message using an interface with the PIC.


Code:
/*
Pins used on MAX6954APL for SPI communications

MAX_DO PIN_C7
MAX_CLK PIN_B6
MAX_DI PIN_B4
MAX_SEL PIN_C6
*/

#define MAX_SEL PIN_C6

void Display (INT adr, int chars) //Function to write to displays
{
   output_low(MAX_SEL);
   spi_write(adr);
   spi_write(chars);
   output_high(MAX_SEL);
}

int digit[] = //Array to address individual displays
{
   0x20, //Digit 0
   0x21, //Digit 1
   0x22, //Digit 2
   0x23, //Digit 3
   0x24, //Digit 4
   0x25, //Digit 5
   0x26, //Digit 6
   0x27  //Digit 7
};

int chars[] = //Array for charecters
{
   0x41,  //  A
   0x42,  //  B
   0x43,  //  C
   0x44,  //  D
   0x45,  //  E
   0x46,  //  F
   0x47,  //  G
   0x48,  //  H
   0x49,  //  I
   0x4A,  //  J
   0x4B,  //  K
   0x4C,  //  L
   0x4D,  //  M
   0x4E,  //  N
   0x4F,  //  O
   0x50,  //  P
   0x51,  //  Q
   0x52,  //  R
   0x53,  //  S
   0x54,  //  T
   0x55,  //  U
   0x56,  //  V
   0x57,  //  W
   0x58,  //  X
   0x59,  //  Y
   0x5A,  //  Z
   0x30,  //  0
   0x31,  //  1
   0x32,  //  2
   0x33,  //  3
   0x34,  //  4
   0x35,  //  5
   0x36,  //  6
   0x37,  //  7
   0x38,  //  8
   0x39,  //  9
   0x20,  // (space)
   0x22,  //  "
   0x24,  //  $
   0x27,  //  '
   0x2A,  //  *
   0x2B,  //  +
   0x2C,  //  ,
   0x2D,  //  -
   0x2E,  //  .
   0x2F,  //  /
   0x3B,  //  ,
   0x3C,  //  <
   0x3D,  //  =
   0x3E,  //  >
   0x3F,  //  ?
   0x40,  //  @
};

int message[] = //Array for message to be stored
{
   36, 36, 36, 36, //Spaces to blank out display at front of message
   36, 36, 36, 36,
   
   7, 4, //Message for use with the lets array (HELLO WORLD)
   11, 11, 14, 36,
   22, 14, 17, 11, 3,
   
   36, 36, 36, 36, //Spaces to blank out display at end of message
   36, 36, 36, 36
};


void main()
{
   INT i=0, array;

   //Setup SPI FOR serial communication to MAX6954APL
   setup_spi (SPI_MASTER|SPI_H_TO_L|SPI_CLK_DIV_16);
   
delay_ms(150);

   //Set Global Inensity to 76
   Display(0x02, 0x13 );

   //Set Configuration REGISTER
   Display(0x04, 0x13 );
   
  array=27-7;
 
   for (i=0;i<array;i++)
   {
   //Set Displays and scroll
   Display(digit[0], chars[message[i]]);
   Display(digit[1], chars[message[i+1]]);
   Display(digit[2], chars[message[i+2]]);
   Display(digit[3], chars[message[i+3]]);
   Display(digit[4], chars[message[i+4]]);
   Display(digit[5], chars[message[i+5]]);
   Display(digit[6], chars[message[i+6]]);
   Display(digit[7], chars[message[i+7]]);
   delay_ms(200);
   
   if (i==array-1)
   {
   i=0;
   delay_ms(150);
   }
   }
}
Matro
Guest







PostPosted: Tue Apr 22, 2008 2:15 am     Reply with quote

Below an example of what could be done to simplify.
Normally this code should work without modifications, but there is no warranty.
Tell me if you have problems with it.
Code:

#include <16F690.h>

#use delay(clock=20000000)

#include <string.h>
/*
Pins used on MAX6954APL for SPI communications

MAX_DO PIN_C7
MAX_CLK PIN_B6
MAX_DI PIN_B4
MAX_SEL PIN_C6
*/

#define MAX_SEL PIN_C6
#define MAX_MSG_LENGTH 50       //maximum message length

#define DIGIT(x) 0x20+x         //macro

void Display (INT adr, int chars) //Function to write to displays
{
   output_low(MAX_SEL);
   spi_write(adr);
   spi_write(chars);
   output_high(MAX_SEL);
}

char message[MAX_MSG_LENGTH];

void main()
{
  int i,j;

  //Setup SPI FOR serial communication to MAX6954APL
  setup_spi (SPI_MASTER|SPI_H_TO_L|SPI_CLK_DIV_16);
  delay_ms(150);
  //Set Global Inensity to 76
  Display(0x02, 0x13 );
  //Set Configuration REGISTER
  Display(0x04, 0x13 );
 
  strcpy(message,"           Hello world!          ");  //initialization of message
  while(1)
  {
    for(i=0;i<strlen(message)-7;i++)
    {
      //Set Displays and scroll
      for(j=0;j<8;j++)
      {
        Display(DIGIT(j),message[i+j]);
      }
      delay_ms(200);
    }
  }
}


Matro
williefeb_19



Joined: 21 Apr 2008
Posts: 18

View user's profile Send private message

PostPosted: Tue Apr 22, 2008 3:25 pm     Reply with quote

Thank You that code works great. I had a feeling there was an easier way of doing this.

I have some questions about the code. What’s converting the "Hello World!" to ASCII and is that a function of strcpy?

I am trying to understand the new code as best I can.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Tue Apr 22, 2008 4:22 pm     Reply with quote

Code:
  setup_spi (SPI_MASTER|SPI_H_TO_L|SPI_CLK_DIV_16);

This configures the SPI port as mode 2, see the table below.

Code:
#define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1  (SPI_L_TO_H)
#define SPI_MODE_2  (SPI_H_TO_L)
#define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)


According to Figure 3 of the max6954 datasheet it should be configured for mode 0 (read the SPI explanation at Wikipedia)

I'm surprised it works with the current setup, better would be to setup like:
Code:
  setup_spi (SPI_MASTER| SPI_MODE_0 |SPI_CLK_DIV_16);
williefeb_19



Joined: 21 Apr 2008
Posts: 18

View user's profile Send private message

PostPosted: Tue Apr 22, 2008 5:06 pm     Reply with quote

I’ve changed the mode to MODE_0 and can’t really tell the difference from before so either way seems to work.
What limits the length of the strings? I can’t go past 70 or so is there a way to go beyond this. I am just curious and don’t know if and/or how it can be done.

Thank You
You have been really helpful


Last edited by williefeb_19 on Wed Apr 23, 2008 6:46 am; edited 1 time in total
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Tue Apr 22, 2008 7:18 pm     Reply with quote

williefeb_19 wrote:
I’ve changed the mode to MODE_0 and can’t really tell the difference from before so either way seems to work.
Either may seem to work, but mode0 is according to specifications and mode3 is by luck (a change to line capacitance, temperature, whatever, can cause it to fail).

Quote:
What limits the length of the strings? I can’t go past 70 or so is there a way to go beyond this.
The method you used for declaring the string stored the data in RAM. On a PIC16 the RAM memory is not contagious but is cut into pieces, banked memory, where the first part of most banks are occupied by general purpose registers. Depending on processor type, RAM bank number and other variables in your program the maximum size of a single string is limited to about 70 characters.

A PIC18 processor is only limited by the total RAM size because it has a different memory layout. Here the RAM still has memory banks but the general purpose registers are moved to the end of the address range, not dividing the RAM in small segments.

There are several ways to work around the 70 character limit but I don't have the time now to work that out. Maybe someone else can give examples?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Apr 22, 2008 7:31 pm     Reply with quote

Quote:
Maybe someone else can give examples?

http://www.ccsinfo.com/forum/viewtopic.php?t=30456&start=4
williefeb_19



Joined: 21 Apr 2008
Posts: 18

View user's profile Send private message

PostPosted: Tue Apr 22, 2008 10:39 pm     Reply with quote

I’ve been reading some of the links posted and these two seem to do what I want to do but I can’t figure out how to implement it.
Like I said in the first post I am new to C programming. I’ve been playing around with it for a while and reading the forums. Trying to figure out as much as I can on my own.


http://www.ccsinfo.com/forum/viewtopic.php?t=21776&highlight=array+banks
http://www.ccsinfo.com/forum/viewtopic.php?t=20955&highlight=writebigarray

Thank You in advance
Matro
Guest







PostPosted: Wed Apr 23, 2008 1:38 am     Reply with quote

williefeb_19 wrote:
Thank You that code works great. I had a feeling there was an easier way of doing this.

I have some questions about the code. What’s converting the "Hello World!" to ASCII and is that a function of strcpy?

I am trying to understand the new code as best I can.

There is no conversion to do. The alpha characters are just a representation for human beings, and ASCII is the same but for a computer.
strcpy() just place the string in RAM so you can use it.
Actually there is no conversion (something based on mathematical calculations) but that's only the representation of the data that is different.

If you really want to see a conversion, so the compiler will transform the alpha-numeric string in ASCII (but at the computer level, the string is already an ASCII array). And on the other side, an LCD or a hyperterminal will transform the ASCII in alpha-numeric string.

I don't know if you understand but it's difficult for me to explain. You have to remove from your mind that a data string (like "Hello world!") and an ASCII array are 2 different things.

For exemple, this 3 examples will give the same thing :
Code:

char string[] = "Hello"   //this way of doing is supported by CCS under special conditions. Prefer the use of strcopy()

Code:

char string[] = {'H','e','l','l','o'}

Code:

char string[] = {0x48,0x65,0x6C,0x6C,0x6F}


Especially the 2 last examples are exactly the same thing for the MCU, because 'H' means "the value of character H in ASCII", and so on.

If it can help you to understand, I can add that in fact for the MCU (and the compiler), the types "char", "byte" and "unsigned int8" are exactly the same type of data. The different names are here for human understanding only. ;-)

Hope this make things more clear for you.

Matro.
williefeb_19



Joined: 21 Apr 2008
Posts: 18

View user's profile Send private message

PostPosted: Wed Apr 23, 2008 6:54 am     Reply with quote

Matro,

That does help make things clearer.

Thanks again
andrewg



Joined: 17 Aug 2005
Posts: 316
Location: Perth, Western Australia

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

PostPosted: Wed Apr 23, 2008 7:12 am     Reply with quote

Strings in C have null terminators, so the correct equivalents are:
Code:
char string[] = "Hello";
char string[] = {'H','e','l','l','o',0};
char string[] = {0x48,0x65,0x6C,0x6C,0x6F,0};

_________________
Andrew
Matro
Guest







PostPosted: Wed Apr 23, 2008 7:18 am     Reply with quote

andrewg wrote:
Strings in C have null terminators, so the correct equivalents are:
Code:
char string[] = "Hello";
char string[] = {'H','e','l','l','o',0};
char string[] = {0x48,0x65,0x6C,0x6C,0x6F,0};

Indeed.
And even to stay everywhere with the same format.
Code:
char string[] = "Hello";
char string[] = {'H','e','l','l','o','\0'};
char string[] = {0x48,0x65,0x6C,0x6C,0x6F,0x00};

Thanks for appending this correction. Wink

Matro.
williefeb_19



Joined: 21 Apr 2008
Posts: 18

View user's profile Send private message

PostPosted: Wed Apr 23, 2008 2:38 pm     Reply with quote

So, if I get an 18F series PIC the string will only be limited by the amount of memory available?

If I wanted to be able to change the message using an interface on the PIC (left, right, up, down and enter button) what would be the best direction to go in?

I know how to take input from buttons and use them in a program. What kind of routine would be used to edit the message in the string?
Matro
Guest







PostPosted: Thu Apr 24, 2008 1:41 am     Reply with quote

Maybe use the interrupt-on-change feature and create the appropriate ISR.
In this ISR, you can simply go through the ASCII table by incrementing or decrementing the value of each character.
For example, left and right key change the string index, up and down change the value at the current index.
The same way as you enter your name with the paddle of a video game console.

It should be a good start that you can customize when it will work.

Matro.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Apr 24, 2008 6:21 pm     Reply with quote

williefeb_19 wrote:
So, if I get an 18F series PIC the string will only be limited by the amount of memory available?
Yes, but take note of:
1) Make sure your compiler supports the 16-bit PIC18. See http://www.ccsinfo.com/content.php?page=Purchasing1
2) In your current design the maximum string length will be limited to the amount of RAM available, a maximum of about 3900 in the largest PIC18's.

I was thinking of alternative approach where you store the text in ROM, this would allow for larger texts even on the PIC16 but I see you want to be able to change the text. That complicates things a bit...
Do you want the modified text to be remembered when power is removed?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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