lcd.c


1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <avr/signal.h>
4
#include <avr/pgmspace.h>
5
#include <avr/sfr_defs.h>
6
7
#include "lcd.h"
8
#include "display.h"
9
#include "delay.h"
10
11
12
void lcd_write(unsigned char data, unsigned char mode);
13
void lcd_enable(void);
14
unsigned char lcd_read(unsigned char mode);
15
unsigned char lcd_waitbusy(void);
16
17
void lcd_init(void)
18
{
19
  LCD_LIGHT_INIT;                            /* set output for contrast and backlight */
20
  LCD_DATA_OUT_INIT;                          /* set output for databytes */
21
  LCD_E_INIT;                              /* set output for enable */
22
  LCD_RS_INIT;                            /* set output for select */
23
  LCD_RW_INIT;                            /* set output for write/read-toggle */
24
  LCD_RS_CLR;                              /* disable lcd */
25
  
26
  cli();
27
  OCR1B = DISPLAY_PWM_TOP;                      /* set display contrast */
28
  OCR1C = DISPLAY_PWM_TOP;                      /* set display backlight */
29
30
  /* init display */
31
  TCNT1 = 0;                              /* set counter to zero */
32
  TCCR1A |= 1<<COM1B1 | 1<<COM1C1 | 1<<WGM11;            /* fast pwm 9-bit, set at top, clear on match */
33
  TCCR1B |= 1<<WGM12 | 1<<CS11;                    /* 8 prescaling: 16 MHz -> 3906 Hz */
34
35
  sei();
36
  delay_ms(16);                            /* power up lcd */
37
  LCD_DATA &= 0x0F;                          /* set 8 bit first (three times) */
38
  LCD_DATA |= 0x30;
39
  lcd_enable();
40
  delay_us(4100);
41
  lcd_enable();
42
  delay_us(40);
43
  lcd_enable();
44
  delay_us(40);
45
  LCD_DATA &= 0x0F;                          /* set 4 bit */
46
  LCD_DATA |= 0x20;
47
  lcd_enable();
48
  delay_us(40);
49
  lcd_write(LCD_CMD_SET_4BIT_2LINE, 0);
50
  delay_us(40);
51
  lcd_write(LCD_CMD_ENTRY_MODE_RN,0);
52
  lcd_write(LCD_CMD_CLEAR, 0);
53
  lcd_write(LCD_CMD_DISPLAY_ON, 0);
54
  return;
55
}
56
57
void lcd_set(uint8_t option, uint16_t value)
58
{
59
  value = DISPLAY_PWM_TOP - value;                  /* invert contrast and backlight */
60
  switch (option) {
61
    case DISPLAY_CONFIG_CONTRAST:
62
    OCR1B = value;
63
    break;
64
  
65
    case DISPLAY_CONFIG_BACKLIGHT:
66
    OCR1C = value;
67
    break;
68
  }
69
  return;
70
}
71
72
void lcd_putc(unsigned char c)
73
{
74
  unsigned char       addr;
75
76
  addr = lcd_waitbusy();
77
  switch (c) {
78
    case '\n':
79
    if (addr < LCD_ADDR_LINE2) addr += 0x40;
80
    else addr -= 0x40;
81
    lcd_write(addr, 0);
82
    break;
83
84
    case '\r':
85
    if (addr < LCD_ADDR_LINE2) addr = LCD_ADDR_LINE1;
86
    else addr = LCD_ADDR_LINE2;
87
    lcd_write(addr, 0);
88
    break;
89
90
    default:
91
    lcd_write(c, 1);
92
    break;
93
  }
94
  return;
95
}
96
97
void lcd_write(unsigned char data, unsigned char mode)
98
{
99
  lcd_waitbusy();
100
  if (mode) LCD_RS_SET;                        /* set to data mode */
101
  else LCD_RS_CLR;                          /* set to instruction mode */
102
  LCD_RW_CLR;                              /* set to write */
103
  LCD_DATA &= 0x0F;                          /* clear output: 0000xxxx */
104
  LCD_DATA |= (data & 0xF0);                      /* first high nibble */
105
  lcd_enable();
106
  LCD_DATA &= 0x0F;                          /* clear output: 0000xxxx */
107
  LCD_DATA |= ((data<<4) & 0xF0);                  /* second low nibble */
108
  lcd_enable();
109
  return;
110
}
111
112
void lcd_enable(void)
113
{
114
  LCD_E_SET;
115
  asm("nop");
116
  asm("nop");
117
  asm("nop");
118
  LCD_E_CLR;
119
  return;
120
}
121
122
unsigned char lcd_read(unsigned char mode)
123
{
124
  unsigned char       data;
125
126
  LCD_DATA_IN_INIT;
127
  if (mode) LCD_RS_SET;                        /* set to data mode */
128
  else LCD_RS_CLR;                          /* set to instruction mode */
129
  LCD_RW_SET;                              /* set to write */
130
  LCD_E_SET;
131
  asm("nop");
132
  asm("nop");
133
  asm("nop");
134
  data = LCD_DATA_IN & 0xF0;
135
  LCD_E_CLR;
136
  asm("nop");
137
  asm("nop");
138
  asm("nop");
139
  LCD_E_SET;
140
  asm("nop");
141
  asm("nop");
142
  asm("nop");
143
  data |= (LCD_DATA_IN & 0xF0)>>4;
144
  LCD_E_CLR;
145
  LCD_DATA_OUT_INIT;
146
  return(data);
147
}
148
149
unsigned char lcd_waitbusy(void)
150
{
151
  while (lcd_read(0) & (1<<LCD_ADDR_BUSY));
152
  delay_us(4);
153
  return(lcd_read(0) | (1<<LCD_ADDR_BUSY));
154
}