avr-gcc-list
[Top][All Lists]
Advanced

[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/



reply via email to

[Prev in Thread] Current Thread [Next in Thread]