Reply by roelof 't Hooft●October 27, 20112011-10-27
On Thu, 2011-10-27 at 00:05 +0000, garycordelli wrote: > oh, and be glad you weren't born 50 years ago...
:)
And ages between 40 and 50, does that count ? ;-)
Just as a little remark apart from the IOxPIN instruction
usage being incorrect is that the following
in the "old days", controlling an I/O port was typically a task left to the
programmer to handle. so, a "port register" (e.g., Io0PIN) was provided that
was an "image" of the binary value most recently stored to the port pin drivers.
so, if you wanted every other pin HI, you might write something like "PORT1 =
0x55" (examples here all use an 8-bit port for brevity). this meant that if you
wanted to set bit 3 of port #1 to HI, you had to say something like "PORT1 |=
0x08". this allows you to set 1 pin while leaving the other 7 pins at their
existing state. if you said "PORT1 = 0x08" instead, you would set bit 3 of the
port, but clear every other bit, because you were setting the actual port
outputs to exactly 0x08. to clear the same single pin, then, you would say
"PORT1 &= ~0x08" to mask out bit 3 while leaving the other bits as is. this
method had two problems. first, it was inefficient because it required you to do
a read-modify-write cycle. second, some architectures had what were essentially
"write-only" port registers. that is, if you wrote to PORT1, it would store the
bits into a latch feeding the pin drivers, but if you read PORT1, it would
read-back the actual pin voltage levels. so, if you wrote a 0x01 to PORT1, and
it drove a load so heavy that the voltage level was pulled down to say 0.5
volts, when you read back PORT1, you might get 0x00 instead of 0x01, thus
causing read-modify-write operations to fail. this forced you to store a "copy"
of your output in RAM somewhere, like "My_Port1 = 0x01; PORT1 = My_Port1;
...(later)... My_Port1 |= 0x08; PORT1 = My_Port1;" yikes!
some architectures responded eventually with "set" and "clear" registers, which
indirectly control the "port output" register. in the case of your LPC device,
Io0SET and Io0CLR feed into Io0PIN. The former is a "write-only" register that
acts like the "set" inputs to an 32-bit flip-flop representing the Io0PIN
register, while Io0CLR is a "write-only" register that acts like the "reset"
inputs to the same 32-bit flip-flop. so, if you use those registers to set or
clear individual pins on the port, you no longer have to keep track of the state
of the rest of the pins. any "0" written to the Io0SET or Io0CLR registers has
no effect, while any "1" written will either set or clear that single bit in the
Io0PIN register. no more read-modify-write inefficiency, and no more worry
about whether reading the actual "port output" register is reading back the
content of the latch itself (i.e., the last value you wrote) or reading back the
actual voltage level of the pin (i.e., as if it represented the actual "inputs"
applied to the port pins).
so, the moral is that you should never be "compelled" to use Io0PIN -- Io0SET
and Io0CLR are there not to make your life miserable (which they would, if they
worked as you described), but to make it easy and carefree. try it yourself in
your code: write a 0x55 to Io0PIN, then check the port pin levels. then write
0x08 to Io0SET and measure the pins again: one additional pin should be HI.
then read Io0SET itself, and you should see that it does not contain the 0x08
you just wrote there, because this register does not "remember" what you write
there -- it simply serves to control the Io0PIN register indirectly.
oh, and be glad you weren't born 50 years ago... :)
--- In l..., "Nagasrinivas" wrote: >
> I was compelled to use IO0PIN register. Let's say we make the following
assigments:
>
> IO0SET = 1<<5;
> IO0CLR = 1<<5;
>
> Now if I want to set that pin again I cannot just set that bit in IO0SET
register. I will have to check if the corresponding bit in IO0CLR is set or not.
Reason being that IO0CLR is given more "importance" over IOxSEt (reference table
132). This unnecessarily complicates the code. Hence the use of IOxPIN and I can
set the pins to any value instantaneously.
>
> Though I did not get the "You do realize that you just set every other bit to
zero, right?" part. What did you mean by that ?
>
> --
> Naga.
> --- In l..., "rtstofer" wrote:
> >
> >
> > I looked over the code and one thing jumps out at me. You use a lot of
> > IO0PIN =
> >
> > You do realize that you just set every other bit to zero, right?
> >
> > A better was to SET a pin is:
> > IO0SET =
> >
> > To clear a pin:
> > IO0CLR =
> >
> > I don't know if this applies to your code but you might want to think
about it. I don't recall ever using IO0PIN > >
> > Richard
>
Reply by rtstofer●October 26, 20112011-10-26
--- In l..., "Nagasrinivas" wrote: >
> I was compelled to use IO0PIN register. Let's say we make the following
assigments:
>
> IO0SET = 1<<5;
> IO0CLR = 1<<5;
>
> Now if I want to set that pin again I cannot just set that bit in IO0SET
register. I will have to check if the corresponding bit in IO0CLR is set or not.
Reason being that IO0CLR is given more "importance" over IOxSEt (reference table
132). This unnecessarily complicates the code. Hence the use of IOxPIN and I can
set the pins to any value instantaneously This is most definitely NOT true. The set and clear registers are just a
one shot event. The hardware just sets or clears the bit and that's it.
Those set and clear registers retain no state whereas the PIN register does.
I guess I don't see any priority mentioned in Table 132 and it
wouldn't make sense to have any. It is only possible for one operation to
take place at any one time.
>
> Though I did not get the "You do realize that you just set every other bit to
zero, right?" part. What did you mean by that ? Let's say you want to set a bit (call it EN) and then set another
bit (call it WR):
IO0PIN = (1 << EN) // sets the enable bit
IO0PIN = (1 << WR) // sets the write bit but clears the enable bit
When you write to IO0PIN, you are writing the entire 32 bit register and
clearing everything that isn't specified as '1' on the right hand
side of the = sign.
Richard
Reply by Nagasrinivas●October 26, 20112011-10-26
I was compelled to use IO0PIN register. Let's say we make the following
assigments:
IO0SET = 1<<5;
IO0CLR = 1<<5;
Now if I want to set that pin again I cannot just set that bit in IO0SET
register. I will have to check if the corresponding bit in IO0CLR is set or not.
Reason being that IO0CLR is given more "importance" over IOxSEt (reference table
132). This unnecessarily complicates the code. Hence the use of IOxPIN and I can
set the pins to any value instantaneously.
Though I did not get the "You do realize that you just set every other bit to
zero, right?" part. What did you mean by that ?
--
Naga.
--- In l..., "rtstofer" wrote: > I looked over the code and one thing jumps out at me.
You use a lot of
> IO0PIN = You do realize that you just set every other bit to zero,
right?
>
> A better was to SET a pin is:
> IO0SET = To clear a pin:
> IO0CLR = I don't know if this applies to your code but you
might want to think about it. I don't recall ever using IO0PIN >
> Richard
>
Reply by rtstofer●October 26, 20112011-10-26
I looked over the code and one thing jumps out at me. You use a lot of
IO0PIN =
You do realize that you just set every other bit to zero, right?
A better was to SET a pin is:
IO0SET =
To clear a pin:
IO0CLR =
I don't know if this applies to your code but you might want to think about
it. I don't recall ever using IO0PIN
Richard
Reply by Nagasrinivas●October 26, 20112011-10-26
Hi,
I am trying to write a LCD for LPC2378. Following is the code I wrote:
/********************************/
/* LCD Driver Module for LPC2378*/
/* by Naga */
/********************************/
/*** This LCD accepts data in ***/
/*** groups of four bits ********/
/* To enable LCD to distinguish between commands and data */
if(mask)
IO0PIN = 1 << SHIFT_RS;
else
IO0PIN = 1 << SHIFT_RS;
/* After we get the upper nibble, set or clear the respective registers */
/*void lcd_print(char *name)
{
unsigned int i = 0;
while(name[i]!='\0')
{
command_data(name[i],1);
delay(DATA_DELAY);
}
}*/
But so far I haven't been even able to initialize the LCD. I would be
grateful if anyone can help me make some progress.
Sincerely,
Naga.
P.S: I will be posting pics of the circuit soon.
Reply by "Felipe de Andrade Neves L."●October 26, 20112011-10-26
lol, my fault.
2011/10/26 Paul Curtis
> **
> It is clear the OP is driving a character-based HD44780 display. A 24-bpp
> driver won't help one iota, so he'll be in trouble from the
start.
>
> --
> Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
> SolderCore running Defender... http://www.vimeo.com/25709426
>
> > -----Original Message-----
> > From: l... [mailto:l...] On
> > Behalf Of Felipe de Andrade Neves L.
> > Sent: 26 October 2011 15:27
> > To: l...
> > Subject: Re: [lpc2000] LPC2378 LCD driver
>
> >
> > Mate, I could not read your code, It is full of register access making
> > it heavy to read, sorry, but I think I can help you, I've got a demo
of
> > my own with a LCD peripherical routine to drive a TFT 24bits screen, if
> > you'd like to have a look on it, this is the link for downloading:
> > http://code.google.com/p/selivre/downloads/detail?name=Drawing%20Demo-
> > platform-rev1.tar.gz#makechanges
> >
> > tell me if you get in trouble with my demo code.
> >
> > 2011/10/25 Nagasrinivas
> >
> > > **
>
> > >
> > >
> > > Hi,
> > >
> > > I am trying to write a LCD driver for lpc2378. Below is the code I
> > wrote:
> > >
> > > /********************************/
> > > /* LCD Driver Module for LPC2378*/
> > > /* by Naga */
> > > /********************************/
> > > /*** This LCD accepts data in ***/
> > > /*** groups of four bits ********/
> > >
> > > #include"lpc23xx.h"
> > >
> > > /******** Declarations **********/
> > >
> > > #define BIT0 (1<<0)
> > > #define BIT1 (1<<1)
> > > #define BIT2 (1<<2)
> > > #define BIT3 (1<<3)
> > >
> > > #define SHIFT_EN 0 /* Connected to P0.0 */ #define SHIFT_RS 8 /*
> > > Connected to P0.8 */ #define SHIFT_BIT0 25 /* Connected to P0.25 */
> > > #define SHIFT_BIT1 18 /* Connected to P1.18 */ #define SHIFT_BIT2 23
> > > /* Connected to P1.23 */ #define SHIFT_BIT3 27 /* Connected to P1.27
> > > */
> > >
> > > #define LCD_DATA_MASK (BIT0|BIT1|BIT2|BIT3)
> > >
> > > #define POWER_DELAY 100000
> > > #define CLEAR_DELAY 5000
> > > #define BIT_DELAY 2000
> > >
> > > const unsigned char lcd_init [5] = {0x33,0x32,0x2C,0x06,0x0C}; char
> > > name[] =
{'N','A','G','A','\0'};
> > >
> > > /****** Function Prototypes *****/
> > >
> > > void init(void);
> > > void delay(unsigned int);
> > > void command_data(unsigned char, int); void clear_screen(void); void
> > > lcd_print(char*);
> > >
> > > /******** main ******************/
> > >
> > > int main()
> > > {
> > > /* Register to set pins P0.0 and P0.8 as GPIO pins */
> > > PINSEL0 = 0x00;
> > >
> > > /* Register to set the pin P0.25 as GPIO pin */
> > > PINSEL1 = 0x00;
> > >
> > > /* Register to set pins P1.18, P1.23, P1.27 as GPIO pins */
> > > PINSEL3 = 0x00;
> > >
> > > /* Register to set the directions of the pins P0.1, P0.8, P0.25 as
> > > outputs*/ IO0DIR = ((1 << 25)|(1 << 8)|(1 << 0));
> > >
> > > /* Register to set the directions of pins P1.18, P1.23, P1.27 as
> > > outputs */ IO1DIR = ((1 << 27)|(1 << 23)|(1 << 18));
> > >
> > > /* Call init function to intialize the lcd */ init();
> > >
> > > /* Function to clear the screen */
> > > //clear_screen();
> > >
> > > while(1)
> > > {
> > > /* Function to print something on the LCD */ //lcd_print(name);
> > > clear_screen(); } }
> > >
> > > void init(void)
> > > {
> > > unsigned int i;
> > >
> > > /* After cd is powered up, give it time to PINtle */
> > > delay(POWER_DELAY);
> > >
> > > /* Send commands to initalize the lcd */ for(i=0; i<5; i++) {
> > > command_data(lcd_init[i], 0); delay(10000); }
> > >
> > > }
> > >
> > > void delay(unsigned int delay)
> > > {
> > > unsigned int i, j;
> > > for(i=0; i
> > > {
> > > for(j=0;j<40;j++);
> > > }
> > > }
> > >
> > > void command_data(unsigned char data, int mask) { unsigned char
> > > upp_nib, low_nib;
> > >
> > > /* upper nibble */
> > > upp_nib = data >> 4;
> > > upp_nib = upp_nib & LCD_DATA_MASK;
> > >
> > >
> > > /* To enable LCD to distinguish between commands and data */
> > > if(mask)
> > > IO0PIN = 1 << SHIFT_RS;
> > > else
> > > IO0PIN = 1 << SHIFT_RS;
> > >
> > > /* After we get the upper nibble, set or clear the respective
> > > registers */
> > >
> > > /* BIT0 */
> > > if(upp_nib & BIT0)
> > > IO0PIN = 1 << SHIFT_BIT0;
> > > else
> > > IO0PIN = 1 << SHIFT_BIT0;
> > >
> > > /* BIT1 */
> > > if(upp_nib & BIT1)
> > > IO1PIN = 1 << SHIFT_BIT1;
> > > else
> > > IO1PIN = 1 << SHIFT_BIT1;
> > >
> > > /* BIT2 */
> > > if(upp_nib & BIT2)
> > > IO1PIN = 1 << SHIFT_BIT2;
> > > else
> > > IO1PIN = 1 << SHIFT_BIT2;
> > >
> > > /* BIT3 */
> > > if(upp_nib & BIT3)
> > > IO1PIN = 1 << SHIFT_BIT3;
> > > else
> > > IO1PIN = 1 << SHIFT_BIT3;
> > >
> > > delay(BIT_DELAY);
> > >
> > > /* Enable signal transition, necessary for LCD to detect the signals
> > > */
> > >
> > > IO0PIN = 1 << SHIFT_EN;
> > > delay(BIT_DELAY);
> > > IO0PIN = 1 << SHIFT_EN;
> > >
> > > /* lower nibble */
> > > low_nib = data & LCD_DATA_MASK;
> > >
> > > /* After we get the upper nibble, set or clear the respective
> > > registers */
> > >
> > > /* BIT0 */
> > > if(low_nib & BIT0)
> > > IO0PIN = 1 << SHIFT_BIT0;
> > > else
> > > IO0PIN = 1 << SHIFT_BIT0;
> > >
> > > /* BIT1 */
> > > if(low_nib & BIT1)
> > > IO1PIN = 1 << SHIFT_BIT1;
> > > else
> > > IO0PIN = 1 << SHIFT_BIT1;
> > >
> > > /* BIT2 */
> > > if(low_nib & BIT2)
> > > IO1PIN = 1 << SHIFT_BIT2;
> > > else
> > > IO1PIN = 1 << SHIFT_BIT2;
> > >
> > > /* BIT3 */
> > > if(low_nib & BIT3)
> > > IO1PIN = 1 << SHIFT_BIT3;
> > > else
> > > IO1PIN = 1 << SHIFT_BIT3;
> > >
> > > delay(BIT_DELAY);
> > >
> > > /* Enable signal transition, necessary for LCD to detect the signals
> > > */ IO0PIN = 1 << SHIFT_EN; delay(BIT_DELAY); IO0PIN = 1 << SHIFT_EN;
> > }
> > >
> > > void clear_screen(void)
> > > {
> > > command_data(0x01,0);
> > > delay(CLEAR_DELAY);
> > > command_data(0x02,0);
> > > delay(CLEAR_DELAY);
> > > }
> > >
> > > /*void lcd_print(char *name)
> > > {
> > > unsigned int i = 0;
> > > while(name[i]!='\0')
> > > {
> > > command_data(name[i],1);
> > > delay(DATA_DELAY);
> > > }
> > > }*/
> > >
> > > But I cannot even get the LCD initialized forget about printing
> > something.
> > > I would really appreciate any help that would enable to make some
> > progress.
> > >
> > > Sincerely,
> > > Naga.
> > >
> > >
> > >
> >
> >
> >
> >
> >
> >
> >
> >
> >
Reply by Paul Curtis●October 26, 20112011-10-26
It is clear the OP is driving a character-based HD44780 display. A 24-bpp
driver won't help one iota, so he'll be in trouble from the start.
> **
> Hi,
>
> I am trying to write a LCD driver for lpc2378. Below is the code I wrote:
>
> /********************************/
> /* LCD Driver Module for LPC2378*/
> /* by Naga */
> /********************************/
> /*** This LCD accepts data in ***/
> /*** groups of four bits ********/
>
> #include"lpc23xx.h"
>
> /******** Declarations **********/
>
> #define BIT0 (1<<0)
> #define BIT1 (1<<1)
> #define BIT2 (1<<2)
> #define BIT3 (1<<3)
>
> #define SHIFT_EN 0 /* Connected to P0.0 */
> #define SHIFT_RS 8 /* Connected to P0.8 */
> #define SHIFT_BIT0 25 /* Connected to P0.25 */
> #define SHIFT_BIT1 18 /* Connected to P1.18 */
> #define SHIFT_BIT2 23 /* Connected to P1.23 */
> #define SHIFT_BIT3 27 /* Connected to P1.27 */
>
> #define LCD_DATA_MASK (BIT0|BIT1|BIT2|BIT3)
>
> #define POWER_DELAY 100000
> #define CLEAR_DELAY 5000
> #define BIT_DELAY 2000
>
> const unsigned char lcd_init [5] = {0x33,0x32,0x2C,0x06,0x0C};
> char name[] =
{'N','A','G','A','\0'};
>
> /****** Function Prototypes *****/
>
> void init(void);
> void delay(unsigned int);
> void command_data(unsigned char, int);
> void clear_screen(void);
> void lcd_print(char*);
>
> /******** main ******************/
>
> int main()
> {
> /* Register to set pins P0.0 and P0.8 as GPIO pins */
> PINSEL0 = 0x00;
>
> /* Register to set the pin P0.25 as GPIO pin */
> PINSEL1 = 0x00;
>
> /* Register to set pins P1.18, P1.23, P1.27 as GPIO pins */
> PINSEL3 = 0x00;
>
> /* Register to set the directions of the pins P0.1, P0.8, P0.25 as
> outputs*/
> IO0DIR = ((1 << 25)|(1 << 8)|(1 << 0));
>
> /* Register to set the directions of pins P1.18, P1.23, P1.27 as outputs */
> IO1DIR = ((1 << 27)|(1 << 23)|(1 << 18));
>
> /* Call init function to intialize the lcd */
> init();
>
> /* Function to clear the screen */
> //clear_screen();
>
> while(1)
> {
> /* Function to print something on the LCD */
> //lcd_print(name);
> clear_screen();
> }
> }
>
> void init(void)
> {
> unsigned int i;
>
> /* After cd is powered up, give it time to PINtle */
> delay(POWER_DELAY);
>
> /* Send commands to initalize the lcd */
> for(i=0; i<5; i++)
> {
> command_data(lcd_init[i], 0);
> delay(10000);
> }
>
> }
>
> void delay(unsigned int delay)
> {
> unsigned int i, j;
> for(i=0; i
> {
> for(j=0;j<40;j++);
> }
> }
>
> void command_data(unsigned char data, int mask)
> {
> unsigned char upp_nib, low_nib;
>
> /* upper nibble */
> upp_nib = data >> 4;
> upp_nib = upp_nib & LCD_DATA_MASK;
> /* To enable LCD to distinguish between commands and data */
> if(mask)
> IO0PIN = 1 << SHIFT_RS;
> else
> IO0PIN = 1 << SHIFT_RS;
>
> /* After we get the upper nibble, set or clear the respective registers */
>
> /* BIT0 */
> if(upp_nib & BIT0)
> IO0PIN = 1 << SHIFT_BIT0;
> else
> IO0PIN = 1 << SHIFT_BIT0;
>
> /* BIT1 */
> if(upp_nib & BIT1)
> IO1PIN = 1 << SHIFT_BIT1;
> else
> IO1PIN = 1 << SHIFT_BIT1;
>
> /* BIT2 */
> if(upp_nib & BIT2)
> IO1PIN = 1 << SHIFT_BIT2;
> else
> IO1PIN = 1 << SHIFT_BIT2;
>
> /* BIT3 */
> if(upp_nib & BIT3)
> IO1PIN = 1 << SHIFT_BIT3;
> else
> IO1PIN = 1 << SHIFT_BIT3;
>
> delay(BIT_DELAY);
>
> /* Enable signal transition, necessary for LCD to detect the signals */
>
> IO0PIN = 1 << SHIFT_EN;
> delay(BIT_DELAY);
> IO0PIN = 1 << SHIFT_EN;
>
> /* lower nibble */
> low_nib = data & LCD_DATA_MASK;
>
> /* After we get the upper nibble, set or clear the respective registers */
>
> /* BIT0 */
> if(low_nib & BIT0)
> IO0PIN = 1 << SHIFT_BIT0;
> else
> IO0PIN = 1 << SHIFT_BIT0;
>
> /* BIT1 */
> if(low_nib & BIT1)
> IO1PIN = 1 << SHIFT_BIT1;
> else
> IO0PIN = 1 << SHIFT_BIT1;
>
> /* BIT2 */
> if(low_nib & BIT2)
> IO1PIN = 1 << SHIFT_BIT2;
> else
> IO1PIN = 1 << SHIFT_BIT2;
>
> /* BIT3 */
> if(low_nib & BIT3)
> IO1PIN = 1 << SHIFT_BIT3;
> else
> IO1PIN = 1 << SHIFT_BIT3;
>
> delay(BIT_DELAY);
>
> /* Enable signal transition, necessary for LCD to detect the signals */
> IO0PIN = 1 << SHIFT_EN;
> delay(BIT_DELAY);
> IO0PIN = 1 << SHIFT_EN;
> }
>
> void clear_screen(void)
> {
> command_data(0x01,0);
> delay(CLEAR_DELAY);
> command_data(0x02,0);
> delay(CLEAR_DELAY);
> }
>
> /*void lcd_print(char *name)
> {
> unsigned int i = 0;
> while(name[i]!='\0')
> {
> command_data(name[i],1);
> delay(DATA_DELAY);
> }
> }*/
>
> But I cannot even get the LCD initialized forget about printing something.
> I would really appreciate any help that would enable to make some progress.
>
> Sincerely,
> Naga.
>
>
>
Reply by Nagasrinivas●October 26, 20112011-10-26
Hi,
I am trying to write a LCD driver for lpc2378. Below is the code I wrote:
/********************************/
/* LCD Driver Module for LPC2378*/
/* by Naga */
/********************************/
/*** This LCD accepts data in ***/
/*** groups of four bits ********/
/* To enable LCD to distinguish between commands and data */
if(mask)
IO0PIN = 1 << SHIFT_RS;
else
IO0PIN = 1 << SHIFT_RS;
/* After we get the upper nibble, set or clear the respective registers */