[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-gcc-list] Source code for user interface menus
From: |
Joerg Wunsch |
Subject: |
Re: [avr-gcc-list] Source code for user interface menus |
Date: |
Mon, 22 Oct 2001 11:19:54 +0200 (MET DST) |
address@hidden (Robert Rozman) wrote:
> I wonder if anyone is willing to share some source code and examples for
> creating user interface on average LCD (2linesX16 characters).
The following has once been an experiment only. Unfortunately, it's
not very well-documented. :) The pin connections are #define'd on
top of the file. It also has example code for downloading a few
characters, and it expects a fully connected HD44780, i. e. the busy
flag needs to be readable.
I think it has been written for a one-line display, but together with
the documentation for the HD44780, it shouldn't be hard to rewrite it
for a two-line display.
/*
* HD44780 LCD display test
*
* Copyright 2001 Joerg Wunsch.
*
* All kinds of warranty disclaimed, use at your own risk. You are
* allowed to freely modify and/or redistribute that code.
*/
#include <io.h>
#include <pgmspace.h>
#define LCD_RS PD5
#define LCD_RW PD6
#define LCD_E PD7
#define LCD_D4 PB0
#define LCD_D5 PB2
#define LCD_D6 PB3
#define LCD_D7 PB4
#define HD44780_CLR 0x01
#define HD44780_HOME 0x02
#define HD44780_ENTMODE(inc, shift) (0x04|(inc? 0x02: 0)|(shift? 1: 0))
#define HD44780_DISPCTL(disp, cursor, blink) \
(0x08|(disp? 0x04: 0)|(cursor? 0x02: 0)|(blink? 1: 0))
#define HD44780_SHIFT(shift, right) \
(0x10|(shift? 0x08: 0)|(right? 0x04: 0))
#define HD44780_FNSET(if8bit, twoline, font8x10) \
(0x20|(if8bit? 0x10: 0)|(twoline? 0x08: 0)|(font8x10? 0x04: 0))
#define HD44780_CGADDR(addr) (0x40|(addr & 0x3f))
#define HD44780_DDADDR(addr) (0x80|(addr & 0x7f))
#define HD44780_BUSYFLAG 0x80
static inline void
lcd_pulse_e(void)
{
sbi(PORTD, LCD_E);
asm volatile("nop"); /* guarantee 500 ns high */
cbi(PORTD, LCD_E);
}
void
lcd_outnibble(uint8_t n, uint8_t rs)
{
uint8_t x;
cbi(PORTD, LCD_RW);
if (rs)
sbi(PORTD, LCD_RS);
else
cbi(PORTD, LCD_RS);
x = (((n & ((BV(LCD_D5)|BV(LCD_D6)|BV(LCD_D7)) >> (LCD_D5 - LCD_D4 - 1)))
<< (LCD_D5 - LCD_D4 - 1)) |
(n & BV(LCD_D4)));
outp(x, PORTB);
lcd_pulse_e();
}
void
lcd_outbyte(uint8_t b, uint8_t rs)
{
lcd_outnibble(b >> 4, rs);
lcd_outnibble(b & 0xf, rs);
}
uint8_t
lcd_innibble(uint8_t rs)
{
uint8_t x;
sbi(PORTD, LCD_RW);
outp(inp(DDRB) & ~(BV(LCD_D4)|BV(LCD_D5)|BV(LCD_D6)|BV(LCD_D7)), DDRB);
if (rs)
sbi(PORTD, LCD_RS);
else
cbi(PORTD, LCD_RS);
lcd_pulse_e();
x = inp(PINB) & (BV(LCD_D4)|BV(LCD_D5)|BV(LCD_D6)|BV(LCD_D7));
outp(inp(DDRB) | (BV(LCD_D4)|BV(LCD_D5)|BV(LCD_D6)|BV(LCD_D7)), DDRB);
cbi(PORTD, LCD_RW);
return (x & BV(LCD_D4)) |
((x & (BV(LCD_D5)|BV(LCD_D6)|BV(LCD_D7))) >> (LCD_D5 - LCD_D4 - 1));
}
uint8_t
lcd_inbyte(uint8_t rs)
{
uint8_t x;
x = lcd_innibble(rs) << 4;
x |= lcd_innibble(rs);
return x;
}
#define lcd_outcmd(n) lcd_outbyte(n, 0)
#define lcd_outdata(n) lcd_outbyte(n, 1)
#define lcd_incmd() lcd_inbyte(0)
#define lcd_indata() lcd_inbyte(1)
void
wait_lcd_ready(void)
{
while (lcd_incmd() & HD44780_BUSYFLAG) ;
}
void
ioinit(void)
{
outp(BV(LCD_D4)|BV(LCD_D5)|BV(LCD_D6)|BV(LCD_D7), DDRB);
outp(BV(LCD_RS)|BV(LCD_RW)|BV(LCD_E), DDRD);
}
static const char chargen[] __attribute__((progmem)) =
{
0x18, 0x14, 0x19, 0x15, 0x12, 0x05, 0x05, 0, /* 0: RX */
0x1c, 0x08, 0x0d, 0x0d, 0x02, 0x05, 0x05, 0, /* 1: TX */
0x08, 0x1f, 0x08, 0x00, 0x02, 0x1f, 0x02, 0, /* 2: <-/-> */
0x02, 0x1f, 0x02, 0x00, 0x02, 0x1f, 0x02, 0, /* 3: ->/-> */
0x00, 0x00, 0x0a, 0x1f, 0x0a, 0x00, 0x00, 0, /* 4: <--> */
0x18, 0x10, 0x14, 0x02, 0x0b, 0x0a, 0x03, 0, /* 5: rit */
};
void
init_chargen(void)
{
uint8_t i;
char c;
lcd_outcmd(HD44780_CGADDR(0));
wait_lcd_ready();
for (i = 0; i < sizeof chargen / sizeof chargen[0]; i++)
{
c = __lpm_inline((uint16_t)(chargen + i));
lcd_outdata(c);
wait_lcd_ready();
}
lcd_outcmd(HD44780_DDADDR(0));
wait_lcd_ready();
}
void
delay1s(void)
{
uint32_t i;
for (i = 0; i < 500000; i++)
;
}
void
main(void)
{
char c;
uint8_t i;
ioinit();
lcd_outnibble(HD44780_FNSET(0, 1, 0) >> 4, 0);
wait_lcd_ready();
lcd_outcmd(HD44780_FNSET(0, 1, 0));
wait_lcd_ready();
lcd_outcmd(HD44780_CLR);
wait_lcd_ready();
lcd_outcmd(HD44780_DISPCTL(1, 1, 0));
wait_lcd_ready();
lcd_outcmd(HD44780_ENTMODE(1, 0));
wait_lcd_ready();
init_chargen();
for (i = 0; i < 80; i++)
{
if (i <= 5)
c = i; /* RAM chargen */
else
c = (i - 6) + '!';
lcd_outdata(c);
wait_lcd_ready();
}
lcd_outcmd(HD44780_DISPCTL(1, 0, 0));
wait_lcd_ready();
for (;;)
{
lcd_outcmd(HD44780_SHIFT(1, 1));
delay1s();
}
}
--
J"org Wunsch Unix support engineer
address@hidden http://www.interface-systems.de/~j/