Topic: tech dcc pc src prev next
tech dcc pc src > lcd.c
#include "lcd.h"
#include <avr/io.h>
#include <util/delay.h>
#include "pins.h"
#define HERMES_LCD_REG_CMD 0
#define HERMES_LCD_REG_DATA 1
void LCD_Send4(unsigned char c, unsigned char reg)
{
/*DDRD |= 0b01101111;*/
// Set all the LCD outputs low.
HERMES_PORT_LCD &= (unsigned char)~(
(1 << HERMES_BIT_LCD_RS) | (1 << HERMES_BIT_LCD_E) |
(1 << HERMES_BIT_LCD_D4) | (1 << HERMES_BIT_LCD_D5) |
(1 << HERMES_BIT_LCD_D6) | (1 << HERMES_BIT_LCD_D7)
);
// Set LCD pins as outputs.
HERMES_DDR_LCD |= (unsigned char)(
(1 << HERMES_BIT_LCD_RS) | (1 << HERMES_BIT_LCD_E) |
(1 << HERMES_BIT_LCD_D4) | (1 << HERMES_BIT_LCD_D5) |
(1 << HERMES_BIT_LCD_D6) | (1 << HERMES_BIT_LCD_D7)
);
// Transfer register and data to the LCD.
HERMES_PORT_LCD = (unsigned char)(
(HERMES_PORT_LCD & 0b10010000) |
((reg ? 1 : 0) << HERMES_BIT_LCD_RS) |
(((c >> 0) & 1) << HERMES_BIT_LCD_D4) |
(((c >> 1) & 1) << HERMES_BIT_LCD_D5) |
(((c >> 2) & 1) << HERMES_BIT_LCD_D6) |
(((c >> 3) & 1) << HERMES_BIT_LCD_D7)
);
// Wait for lines to settle.
_delay_us(30);
// Enable the LCD for 2us to store the data.
HERMES_PORT_LCD =
(unsigned char)(HERMES_PORT_LCD & ~(1 << HERMES_BIT_LCD_E));
_delay_us(2);
HERMES_PORT_LCD =
(unsigned char)(HERMES_PORT_LCD | (1 << HERMES_BIT_LCD_E));
_delay_us(2);
HERMES_PORT_LCD =
(unsigned char)(HERMES_PORT_LCD & ~(1 << HERMES_BIT_LCD_E));
_delay_us(50);
}
void LCD_Send(unsigned char c, unsigned char reg)
{
LCD_Send4(c >> 4, reg);
LCD_Send4(c, reg);
}
void LCD_Init()
{
// Set LCD pins as outputs.
HERMES_DDR_LCD |= (unsigned char)(
(1 << HERMES_BIT_LCD_D4) |
(1 << HERMES_BIT_LCD_D5) |
(1 << HERMES_BIT_LCD_D6) |
(1 << HERMES_BIT_LCD_D7) |
(1 << HERMES_BIT_LCD_E) |
(1 << HERMES_BIT_LCD_RS)
);
HERMES_PORT_LCD &= (unsigned char)~(
(1 << HERMES_BIT_LCD_D4) |
(1 << HERMES_BIT_LCD_D5) |
(1 << HERMES_BIT_LCD_D6) |
(1 << HERMES_BIT_LCD_D7) |
(1 << HERMES_BIT_LCD_E) |
(1 << HERMES_BIT_LCD_RS)
);
_delay_us(50000);
// Set 8 bit mode.
LCD_Send4(0b0011, 0);
LCD_Send4(0b0011, 0);
LCD_Send4(0b0011, 0);
// Set 4 bit mode.
LCD_Send4(0b0010, 0);
// 4-bit, 2 lines, normal font.
LCD_Send(0b00101000, 0);
// Entry mode left to right, no display shift.
LCD_Send(0b00000110, 0);
// Display on, cursor off, not blinking.
LCD_Send(0b00001100, 0);
LCD_Clear();
}
void LCD_ReInit()
{
// Set 8 bit mode.
LCD_Send4(0b0011, 0);
LCD_Send4(0b0011, 0);
LCD_Send4(0b0011, 0);
// Set 4 bit mode.
LCD_Send4(0b0010, 0);
// 4-bit, 2 lines, normal font.
LCD_Send(0b00101000, 0);
// Entry mode left to right, no display shift.
LCD_Send(0b00000110, 0);
// Display on, cursor off, not blinking.
LCD_Send(0b00001100, 0);
LCD_Clear();
}
void LCD_Clear()
{
// Clear the screen.
LCD_Send(0b00000001, 0);
_delay_us(2000);
// Return home.
LCD_Send(0b00000010, 0);
_delay_us(2000);
// Reset cursor mode.
LCD_Send(0b00001100, 0);
_delay_us(2000);
}
void LCD_PutC(char c)
{
LCD_Send((unsigned char)c, 1);
}
void LCD_PutS(const char *s)
{
while(*s != 0)
{
LCD_PutC((char)*s);
++s;
}
}
void LCD_PutI(int i)
{
if(i < 0)
{
LCD_PutC('-');
LCD_PutI(-i);
return;
}
if(i > 9)
LCD_PutI((int)(i / 10));
LCD_PutC((char)('0' + (i % 10)));
}
void LCD_Move(unsigned char col, unsigned char row)
{
LCD_Send((unsigned char)(0x80 + 0x40 * row + col), 0);
}
void LCD_Cursor()
{
// Enable cursor and cursor blinking.
LCD_Send((unsigned char)0x0d, HERMES_LCD_REG_CMD);
}
void LCD_CursorMove(unsigned char col, unsigned char row)
{
LCD_Cursor();
LCD_Move(col, row);
}
void LCD_CursorHide()
{
// Hide the cursor, leaving the display on.
LCD_Send((unsigned char)0x0c, HERMES_LCD_REG_CMD);
}
unsigned char LCD_DigitCount(int n)
{
unsigned char c = 1;
if(n < 0)
{
++c;
n = -n;
}
while(n > 9)
{
++c;
n /= 10;
}
return c;
}
void LCD_PrintListIndex(int index, int length)
{
LCD_Move((unsigned char)(13 - LCD_DigitCount(index) - LCD_DigitCount(length)), 0);
LCD_PutI(index);
LCD_PutS(" / ");
LCD_PutI(length);
}
void LCD_DefineCustomChar(unsigned char index, const unsigned char *data)
{
LCD_Send((unsigned char)(0b01000000 | ((index & 0b0000111) << 3)), HERMES_LCD_REG_CMD);
for(unsigned char i = 0; i < 8; ++i)
LCD_Send(data[i], HERMES_LCD_REG_DATA);
}
static const unsigned char character_up[8] = {
0b00000,
0b00000,
0b01000,
0b11100,
0b01000,
0b01111,
0b00000,
0b00000
};
static const unsigned char character_left[8] = {
0b00000,
0b00000,
0b01000,
0b11111,
0b01000,
0b00000,
0b00000,
0b00000
};
static const unsigned char character_right[8] = {
0b00000,
0b00000,
0b00010,
0b11111,
0b00010,
0b00000,
0b00000,
0b00000
};
static const unsigned char character_ok[8] = {
0b00000,
0b00000,
0b00000,
0b00001,
0b10010,
0b01100,
0b00000,
0b00000
};
static const unsigned char character_hb[8] = {
0b10101,
0b01010,
0b10101,
0b01010,
0b10101,
0b01010,
0b10101,
0b01010
};
static const unsigned char character_acw[8] = {
0b00000,
0b01110,
0b11000,
0b10000,
0b10000,
0b11010,
0b01111,
0b00010
};
static const unsigned char character_cw[8] = {
0b00000,
0b01110,
0b00011,
0b00001,
0b00001,
0b01011,
0b11110,
0b01000
};
static const unsigned char character_button_top[8] = {
0b00000,
0b01110,
0b01110,
0b00000,
0b00000,
0b00000,
0b00000,
0b00000
};
static const unsigned char character_button_bottom[8] = {
0b00000,
0b00000,
0b00000,
0b00000,
0b00000,
0b01110,
0b01110,
0b00000
};
static const unsigned char character_button_both[8] = {
0b00000,
0b01110,
0b01110,
0b00000,
0b00000,
0b01110,
0b01110,
0b00000
};
void LCD_DefineHermesChars(unsigned char mode)
{
static unsigned char g_mode = HERMES_LCD_CUSTOM_MODE_UNDEFINED;
if(mode == g_mode)
return;
g_mode = mode;
switch(mode)
{
case HERMES_LCD_CUSTOM_MODE_OPS:
LCD_DefineCustomChar(HERMES_LCD_CHAR_HB, character_hb);
LCD_DefineCustomChar(HERMES_LCD_CHAR_BUTTON_TOP, character_button_top);
LCD_DefineCustomChar(HERMES_LCD_CHAR_BUTTON_BOTTOM, character_button_bottom);
LCD_DefineCustomChar(HERMES_LCD_CHAR_BUTTON_BOTH, character_button_both);
break;
case HERMES_LCD_CUSTOM_MODE_MENU:
LCD_DefineCustomChar(HERMES_LCD_CHAR_UP, character_up);
LCD_DefineCustomChar(HERMES_LCD_CHAR_L, character_left);
LCD_DefineCustomChar(HERMES_LCD_CHAR_R, character_right);
LCD_DefineCustomChar(HERMES_LCD_CHAR_OK, character_ok);
LCD_DefineCustomChar(HERMES_LCD_CHAR_ACW, character_acw);
LCD_DefineCustomChar(HERMES_LCD_CHAR_CW, character_cw);
break;
};
}