/*
SUMMARY OF IMPORTANT LCD1602 COMMANDS
GIVEN 2 LINE MODE - 0X38 .THE WORD DISPLAY BEGINS FROM THE CURSOR POSITION
THE ROW 1 ADDRESS IN DDRAM IS FROM 0X80 TO 0X8F FOR 16 COLS
THE ROW 2 ADDRESS IN DDRAM IS FROM 0XC0 TO 0XCF FOR 16 COLS
FEED THE ABOVE DDRAM POS ADDRESS AND WORD DISPLAY WILL START
FROM THE ADDRESS
THE 1 LINE MODE - 0X30 ONLY ROW 1 DDRAM ADDRESS MATTERS
TO SIMPLY SHIFT THE DISPLAY RIGHT FROM BEGINNING ONE TIME - 0X1C
TO SIMPLY SHIFT THE DISPLAY LEFT ONE TIME - 0X18
TO SIMPLY SHIFT THE CURSOR RIGHT FROM BEGINNING ONE TIME - 0X14
TO SIMPLY SHIFT THE CURSOR LEFT ONE TIME - 0X10
DISPLAY CONFIGURE COMMANDS
0X01- CLEAR THE DISPLAY
0X0C - DISPLAY ON, CURSOR OFF, BLINK OFF
0X0E - DISPLAY AND CURSOR ON, BLINK OFF
0X0F- DISPLAY, CURSOR AND BLINK IS ON
TO SHIFT CURSOR AND/OR DISPLAY USING ENTRY MODE INCREMENT OR DECREMENT
0X06- ONLY CURSOR GOES RIGHT
0X07 - BOTH CURSOR AND DISPLAY GO RIGHT
0X04 - ONLY CURSOR MOVES LEFT
*/
#define E 0
#define RS 1
volatile uint8_t *porta = (volatile uint8_t *)0x22;
volatile uint8_t *portb = (volatile uint8_t *)0x25;
void my_delay(long t)
{
for(volatile long i = 0; i< t*1000; i++);
}
void pulse_enable(void)
{
*portb |= (1 << E);
my_delay(1);
*portb &= ~(1 << E);
}
void command(uint8_t c)
{
*portb &= ~(1 << RS); /*RS = 0 FOR COMMAND*/
*porta = c;
pulse_enable();
my_delay(2);
}
void data(uint8_t d)
{
*portb |= (1 << RS); /*RS = 1 FOR DATA*/
*porta = d;
pulse_enable();
my_delay(2);
}
void lcd_init_1()
{
command(0x30); // Function set: 8-bit, 1-line
command(0x0E); // Display ON, cursor ON
command(0x01); // Clear display
command(0x06); // Entry mode set: increment
}
void lcd_init_2()
{
command(0x38); // Function set: 8-bit, 2-line
command(0x0E); // Display ON, cursor ON
command(0x01); // Clear display
command(0x06); // Entry mode set: increment
}
uint8_t w1[8] = "Welcome";
uint8_t w2[11] = "To ETALVIS";
uint8_t r1[16] = {0x8f,0x8e,0x8d,0x8c,0x8b,0x8a,0x89,0x88,0x87,0x86,0x85,0x84,0x83,0x82,0x81,0x80};
/*move left in row 2*/
uint8_t r2[16] = {0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf};
void setup() {
volatile uint8_t *ddra = (volatile uint8_t *)0x21;
volatile uint8_t *ddrb = (volatile uint8_t *)0x24;
*ddra = 0xff;
*ddrb = 0x03;
}
void p1(uint8_t *x) /*by default left justified*/
{
int i = 0;
int j = 7;
lcd_init_1();
while(x[i] != '\0')
{
data(x[i]);
i++;
my_delay(20);
}
while(1);
}
/*method 1 manually shift the cursor to right side by 8 positions
and here cursor addr starts at the default position of the screen
and then start sending the data*/
void left_justified_1(uint8_t *w)
{
int j = 0;
lcd_init_1();
/*right justified hence we shift the cursor to the right*/
for(int i = 0; i<8; i++)
command(0x14);
while( w[j] != '\0')
{
data(w[j]);
j++;
my_delay(20);
}
while(1);
}
/*method 2 the cursor position starts at the 8th cell of row 1
no need to shift it to the right*/
void left_justified_2(uint8_t *w)
{
int j = 0;
lcd_init_1();
/*start the cursor to the right by 8 positions
and then send the data to accomodate 7 letter word welcome*/
command(0x88);
while( w[j] != '\0')
{
data(w[j]);
j++;
my_delay(20);
}
while(1);
}
void p2(uint8_t *w)
{
left_justified_2(w);
}
/*method 2 to increment addr of the cursor to middle
by command of cursor addr to start data display from
the middle*/
void to_middle_2(uint8_t *w)
{
/*command to start cursor at the 4th cell*/
lcd_init_1();
command(0x84);
int i = 0;
while( w[i] != '\0')
{
data(w[i]);
i++;
my_delay(20);
}
while(1);
}
void p3(uint8_t *w)
{
to_middle_2(w);
}
/*displaying the data in row 2 general scheme is
row 1 base address is 0x80 and row 2 base address is 0xc0
so if command(0xc0) then the cursors starts at col 0 of row 2
but the LCD must be configured in 2 lines mode*/
void show_left_row2(uint8_t *w)
{
lcd_init_2();
command(0xc0);
int i = 0;
while( w[i] != '\0')
{
data(w[i]);
i++;
my_delay(20);
}
while(1);
}
void p4(uint8_t *w)
{
show_left_row2(w);
}
void show_right_row2(uint8_t *w)
{
lcd_init_2();
command(0xc8);
int i = 0;
while(w[i] != '\0')
{
data(w[i]);
i++;
my_delay(20);
}
while(1);
}
void p5(uint8_t *w)
{
show_right_row2(w);
}
void to_middle_row2(uint8_t *w)
{
lcd_init_2();
command(0xc4); /*start the cursor at col 4 of row 2*/
int i = 0;
while( w[i] != '\0')
{
data(w[i]);
i++;
my_delay(20);
}
while(1);
}
void p6(uint8_t *w)
{
to_middle_row2(w);
}
void two_words(uint8_t *w1, uint8_t *w2) /*each string has extra \0 to stop overlap
in the display*/
{
lcd_init_2();
command(0x84); /*start word 1 at col 4 on row 1*/
int i = 0;
while(w1[i] != '\0')
{
data(w1[i]);
i++;
}
my_delay(100);
command(0xc4);/*start word 2 at col4 on the row 2*/
int j = 0;
while(w2[j] != '\0')
{
data(w2[j]);
j++;
}
while(1);
}
void p7(uint8_t *w1, uint8_t *w2)
{
two_words(w1,w2);
}
void display_word(uint8_t *w,uint8_t x)
{
lcd_init_2();
command(x);
int j = 0;
while( w[j] != '\0')
{
data(w[j]);
j++;
}
}
void go_left(uint8_t *w, uint8_t *right)
{
for(int i = 0; i<16; i++)
{
display_word(w,right[i]);
my_delay(100);
}
}
void p8(uint8_t *w, uint8_t *dir)
{
go_left(w,dir);
}
void go_right(uint8_t *w, uint8_t *right, int limit)
{
for(int i = 0; i<limit; i++)
{
display_word(w,right[i]);
my_delay(100);
}
}
void p9(uint8_t *w, uint8_t *right, int limit)
{
go_right(w,right,limit);
}
void two_words_middle(uint8_t *w1, uint8_t *w2, uint8_t *c1, uint8_t *c2, int limit1, int limit2)
{
for(int i = 0; i<limit1; i++)
{
display_word(w1,c1[i]);
my_delay(100);
}
my_delay(100);
for(int i = 0; i<limit2; i++)
{
display_word(w2,c2[i]);
my_delay(100);
}
}
void two_words_middle_1(uint8_t *w1, uint8_t *w2, uint8_t *c1, uint8_t *c2, int limit1, int limit2)
{
for(int i = 0; i<limit1; i++)
{
display_word(w1,c1[i]);
my_delay(100);
}
display_word(w1,0x84);
my_delay(1000);
for(int i = 0; i<limit2; i++)
{
display_word(w2,c2[i]);
my_delay(100);
}
display_word(w2,0xcd);
my_delay(10);
while(1) {
display_word(w1,0x84);
my_delay(100);
display_word(w2,0xc4);
my_delay(100);
}
}
void p10(uint8_t *w1, uint8_t *w2, uint8_t *c1, uint8_t *c2, int l1, int l2)
{
two_words_middle_1(w1,w2,c1,c2,l1,l2);
}
void loop() {
p10(w1,w2,r1,r2,12,3);
}