Code: Select all
//lc7981.h file
/* AVR clock speed */
//#define F_CPU 8000000
//#include <avr/io.h>
//#include <util/delay.h>
/* Hardware setup */
//#define LCD_DATA_DDR DDRA
#define LCD_DATA_PORT PORTD
//#define LCD_DATA_PIN PINA
//#define LCD_CTRL_DDR DDRB
//#define LCD_CTRL_PORT PORTB
#define LCD_CTRL_RS PORTB.F0
#define LCD_CTRL_RW PORTB.F1
#define LCD_CTRL_E PORTB.F2
#define LCD_WIDTH 160
#define LCD_HEIGHT 80
/* Convenient macros to toggle RS, RW, and E control pins */
#define lcd_rs_high() (PORTB.F0 = 1) // wonder if this work
#define lcd_rs_low() (PORTB.F0 = 0) // wonder if this work
#define lcd_rw_high() (PORTB.F1 = 1) // wonder if this work
#define lcd_rw_low() (PORTB.F1 = 0) // wonder if this work
#define lcd_enable_high() (PORTB.F2 = 1) // wonder if this work
#define lcd_enable_low() (PORTB.F2 = 0) // wonder if this work
/* All possible instructions for the LCD Instruction Register */
#define LCD_CMD_MODE 0x00
#define LCD_CMD_CHAR_PITCH 0x01
#define LCD_CMD_NUM_CHARS 0x02
#define LCD_CMD_TIME_DIVISION 0x03
#define LCD_CMD_CURSOR_POS 0x04
#define LCD_CMD_DISPLAY_START_LA 0x08
#define LCD_CMD_DISPLAY_START_HA 0x09
#define LCD_CMD_CURSOR_LA 0x0A
#define LCD_CMD_CURSOR_HA 0x0B
#define LCD_CMD_WRITE_DATA 0x0C
#define LCD_CMD_READ_DATA 0x0D
#define LCD_CMD_CLEAR_BIT 0x0E
#define LCD_CMD_SET_BIT 0x0F
/* Bits of the LCD Mode Control Register (DB5-DB0) */
#define LCD_MODE_ON_OFF 32
#define LCD_MODE_MASTER_SLAVE 16
#define LCD_MODE_BLINK 8
#define LCD_MODE_CURSOR 4
#define LCD_MODE_MODE 2
#define LCD_MODE_EXTERNAL 1
/* Possible settings of the character pitch register */
/* Horizontal character pitches of 6, 7, and 8 */
#define LCD_CHAR_PITCH_HP_6 0x05
#define LCD_CHAR_PITCH_HP_7 0x06
#define LCD_CHAR_PITCH_HP_8 0x07
/* To indicate the state of a pixel */
#define PIXEL_ON 0xFF
#define PIXEL_OFF 0x00
/* Low-level LCD interface functions */
void lcd_strobe_enable(void);
void lcd_write_command(unsigned char command, unsigned char data);
void lcd_wait_busy(void);
/* LCD Graphics interface */
void lcd_graphics_init(void);
void lcd_graphics_clear(void);
void lcd_graphics_move(unsigned short x, unsigned short y);
void lcd_graphics_draw_byte(unsigned char data);
void lcd_graphics_plot_byte(unsigned short x, unsigned short y, unsigned char data);
void lcd_graphics_plot_pixel(unsigned short x, unsigned short y, unsigned char state);
Code: Select all
// lc7981.c file
#include "lc7981.h"
#include "graphics.c"
//#include "draw_penguin.c"
/**
* Strobes the Enable control line to trigger the lcd to process the
* transmitted instruction.
*/
void lcd_strobe_enable(void) {
lcd_enable_high();
__asm("nop;"); __asm("nop;"); __asm("nop;");
lcd_enable_low();
__asm("nop;"); __asm("nop;"); __asm("nop;");
}
/**
* Waits for the busy flag to clear, which should take
* around the maximum time for an instruction to complete.
* Note, LCD operation is kind of sensitive to this configuration. If the delay
* is too fast, the LCD will miss some pixels when it is really put through
* a stress test. This dela time seems to work great.
*/
void lcd_wait_busy(void) {
Delay_us(3);
}
/**
* Writes a raw instruction to the LCD.
* @param command The 4-bit instruction code.
* @param data The 8-bit paramater/data to the specified instruction.
*/
void lcd_write_command(unsigned char command, unsigned char data) {
/* Wait for the busy flag to clear */
lcd_wait_busy();
/* Set RW low, RS high to write the instruction command */
lcd_rw_low();
lcd_rs_high();
/* Instruction commands are a maximum of 4 bits long, so
* just mask off the rest. */
LCD_DATA_PORT = (command&0x0F);
__asm("nop;"); __asm("nop;"); __asm("nop;");
__asm("nop;"); __asm("nop;"); __asm("nop;");
lcd_strobe_enable();
__asm("nop;"); __asm("nop;"); __asm("nop;");
__asm("nop;"); __asm("nop;"); __asm("nop;");
/* Set RW low, RW low to write the instruction data */
lcd_rw_low();
lcd_rs_low();
LCD_DATA_PORT = data;
__asm("nop;"); __asm("nop;"); __asm("nop;");
__asm("nop;"); __asm("nop;"); __asm("nop;");
lcd_strobe_enable();
__asm("nop;"); __asm("nop;"); __asm("nop;");
__asm("nop;"); __asm("nop;"); __asm("nop;");
}
/**
* Initializes the LCD in graphics mode.
* Uses a character pitch of 8 (8 bits are plotted whenever a byte is drawn)
*/
void lcd_graphics_init(void) {
unsigned char commandData;
/* Set the data direction registers apprioriately */
TRISD = 0;
TRISB = 0;
/* Assert all control lines to low */
lcd_rw_low();
lcd_rs_low();
lcd_enable_low();
/* Send mode configuration command with
* Toggle Display On, Master, Mode Graphics bits set */
commandData = LCD_MODE_ON_OFF | LCD_MODE_MASTER_SLAVE | LCD_MODE_MODE;
lcd_write_command(LCD_CMD_MODE, commandData);
/* Send the set character pitch command with horizontal
* character pitch of 8 (so 8 pixels are painted when we draw) */
commandData = LCD_CHAR_PITCH_HP_8;
lcd_write_command(LCD_CMD_CHAR_PITCH, commandData);
/* Send the number of characters command with the total
* number of graphics bytes that can be painted horizontally
* (width/8) */
commandData = (LCD_WIDTH/8)-1;
lcd_write_command(LCD_CMD_NUM_CHARS, commandData);
/* Set the time division */
commandData = 128-1;
lcd_write_command(LCD_CMD_TIME_DIVISION, commandData);
/* Set the display low/high start address to 0x00 (left corner) */
commandData = 0x00;
lcd_write_command(LCD_CMD_DISPLAY_START_LA, commandData);
lcd_write_command(LCD_CMD_DISPLAY_START_HA, commandData);
/* Reset the cursor to home 0x00 (left corner) */
commandData = 0x00;
lcd_write_command(LCD_CMD_CURSOR_LA, commandData);
lcd_write_command(LCD_CMD_CURSOR_HA, commandData);
}
/**
* Moves the LCD cursor to the specified coordinates.
* @param x The new x coordinante of the cursor.
* @param y The new y coordinante of the cursor.
*/
void lcd_graphics_move(unsigned short x, unsigned short y) {
unsigned short pos;
/* Calculate the raw address in terms of bytes on the screen */
pos = ((y*LCD_WIDTH)+x)/8;
/* Move the cursor to the new address */
lcd_write_command(LCD_CMD_CURSOR_LA, pos&0xFF);
lcd_write_command(LCD_CMD_CURSOR_HA, pos>>8);
}
/**
* Draws a byte to the LCD at the current LCD's cursor location.
* @param data The byte to draw. The pixels are drawn MSB to LSB.
*/
void lcd_graphics_draw_byte(unsigned char data) {
lcd_write_command(LCD_CMD_WRITE_DATA, data);
}
/**
* Plots a byte at the specified coordinates.
* @param x The x coordinante of the byte to be drawn.
* @param y The y coordinante of the byte to be drawn.
* @param data The byte to draw. The pixels are drawn MSB to LSB.
*/
void lcd_graphics_plot_byte(unsigned short x, unsigned short y, unsigned char data) {
lcd_graphics_move(x, y);
lcd_graphics_draw_byte(data);
}
/**
* Plots a pixel at the specified coordinates.
* @param x The x coordinante of the pixel.
* @param y The y coordinante of the pixel.
* @param state PIXEL_ON to set the pixel, otherwise pixel will be cleared.
*/
void lcd_graphics_plot_pixel(unsigned short x, unsigned short y, unsigned char state) {
unsigned char pos;
lcd_graphics_move(x, y);
/* Since lcd_graphics_move() moves the cursor to a particular
* byte, not bit, we need the relative distance to the specified
* bit we are going to set/clear. */
pos = x%8;
if (state == PIXEL_ON)
lcd_write_command(LCD_CMD_SET_BIT, pos);
else
lcd_write_command(LCD_CMD_CLEAR_BIT, pos);
}
/**
* Clears the LCD screen
*/
void lcd_graphics_clear(void) {
unsigned short i;
/* Move cursor to home (top left corner) */
lcd_graphics_move(0, 0);
/* Draw empty bytes to ocucpy the entire screen */
for (i = 0; i < ((LCD_WIDTH*LCD_HEIGHT)/8); i++)
lcd_graphics_draw_byte(0x00);
}
/**
* Delay in milliseconds.
* An extension of _delay_ms() so we can delay for longer periods of time.
* @param ms Milliseconds to delay.
*/
void delay_ms_long(unsigned short ms) {
for (; ms > 0; ms--)
Delay_ms(1);
}
int main(void) {
lcd_graphics_init();
lcd_graphics_clear();
g_draw_rectangle(6, 5, 100, 30);
g_draw_rectangle(8, 7, 100, 30);
g_draw_rectangle(10, 9, 100, 30);
g_draw_rectangle(12, 11, 100, 30);
g_draw_string(17, 15, "Graphics Demo!\nHello World!");
//draw_penguin(); // this i removed it´s not in the project
g_draw_string(22, 44, "!\"#$%&'=\n()*+,-./\n:;<>?@\[\n]^_`|{}");
while (1) ;
return 0;
}
Code: Select all
// graphics.h
#include "font5x7.h"
#define FONT_WIDTH 5
#define FONT_HEIGHT 7
void g_draw_horizontal_line(unsigned short x, unsigned short y, unsigned short length);
void g_draw_vertical_line(unsigned short x, unsigned short y, unsigned short length);
void g_draw_rectangle(unsigned short x, unsigned short y, unsigned short width, unsigned short height);
void g_draw_char(unsigned short x, unsigned short y, char character);
void g_draw_string(unsigned short x, unsigned short y, const char *str);
Code: Select all
//graphics.c
#include "graphics.h"
/**
* Draws a horizontal line, left to right, at the specified coordinates and of
* the specified length.
* @param x The x coordinante of the line's origin.
* @param y The y coordinante of the line's origin.
* @param length The length of the line, in pixels.
*/
void g_draw_horizontal_line(unsigned short x, unsigned short y, unsigned short length) {
unsigned short i;
for (i = x; i <= x+length; i++)
lcd_graphics_plot_pixel(i, y, PIXEL_ON);
}
/**
* Draws a vertical line, top to bottom, at the specified coordinates and of
* the specified length.
* @param x The x coordinante of the line's origin.
* @param y The y coordinante of the line's origin.
* @param length The length of the line, in pixels.
*/
void g_draw_vertical_line(unsigned short x, unsigned short y, unsigned short length) {
unsigned short i;
for (i = y; i < y+length; i++)
lcd_graphics_plot_pixel(x, i, PIXEL_ON);
}
/**
* Draws a rectangle. The coordinantes specify the top left corner of the
* rectangle.
* @param x The x coordinante of the rectangle's origin.
* @param y The y coordinante of the rectangle's origin.
* @param width The width of the rectangle, in pixels.
* @param height The height of the rectangle, in pixels.
*/
void g_draw_rectangle(unsigned short x, unsigned short y, unsigned short width, unsigned short height) {
/* Adjust width and height because x and y coordinates start on 0,0 */
width--;
height--;
g_draw_horizontal_line(x, y, width);
g_draw_vertical_line(x, y, height);
g_draw_vertical_line(x+width, y, height);
g_draw_horizontal_line(x, y+height, width);
}
/**
* Draws a 5x7 character to the screen. The coordinantes specify the top left
* corner of the character.
* Characters outside the character set will not be drawn (function will return
* immediately).
* @param x The x coordinate of the character's origin.
* @param y The y coordinate of the character's origin.
* @param character The ASCII character to draw.
*/
void g_draw_char(unsigned short x, unsigned short y, char character) {
unsigned char fontIndex, i, j;
/* The 5x7 character set starts at the '!' character (ASCII index
* number 33) so we subtract 32 from the ASCII character to find the
* index in the 5x7 font table. */
fontIndex = character-32;
/* If the index is out of bounds, bail out */
if (fontIndex > 94)
return;
for (i = 0; i < FONT_WIDTH; i++) {
for (j = 0; j < FONT_HEIGHT; j++) {
/* Check if the bit/pixel is set, paint accoringly to
* the screen */
if (Font5x7[FONT_WIDTH*fontIndex+i] & (1<<j))
lcd_graphics_plot_pixel(x, y+j, PIXEL_ON);
else
lcd_graphics_plot_pixel(x, y+j, PIXEL_OFF);
}
/* Move the LCD cursor through the font width as well */
x++;
}
}
/**
* Draws a string of characters to the screen. The characters will be drawn in i
* 5x7 font.
* The coordinantes specify the top left corner of the first character in the
* string.
* Characters will be wrapped. The newline character is supported.
* Characters outside the 5x7 character set will not be drawn.
* @param x The x coordinate of the string's first character's origin.
* @param y The y coordinate of the string's first character's origin.
* @param str The null-terminated ASCII string of characters.
*/
void g_draw_string(unsigned short x, unsigned short y, const char *str) {
unsigned short origin_X;
/* Preserve the origin X, in case of a new line */
origin_X = x;
/* Continue through the string until we encounter a null character */
while (*str != '\0') {
/* If the character is a newline, then prepare our x and y
* coordinates for the next character on the new line. */
if (*str == '\n') {
/* Reset x to its origin */
x = origin_X;
/* Move y one character down */
y += FONT_HEIGHT+1;
str++;
continue;
}
g_draw_char(x, y, *str++);
/* Add a 1-pixel spacing between the characters */
x += FONT_WIDTH+1;
/* In case we are putting this character out of bounds,
* move the character to the next line on the display */
if ((x+FONT_WIDTH) > LCD_WIDTH) {
/* Reset x to its origin */
x = origin_X;
/* Move y one character down */
y += FONT_HEIGHT+1;
}
}
}
Code: Select all
//font5x7.h files
#ifndef FONT5X7_H
#define FONT5X7_H
// standard ascii 5x7 font
// defines ascii characters 0x20-0x7F (32-127)
//static unsigned char __attribute__ ((progmem)) Font5x7[] = {
static unsigned char Font5x7[] = {
0x00, 0x00, 0x00, 0x00, 0x00,// (space)
0x00, 0x00, 0x5F, 0x00, 0x00,// !
0x00, 0x07, 0x00, 0x07, 0x00,// "
0x14, 0x7F, 0x14, 0x7F, 0x14,// #
0x24, 0x2A, 0x7F, 0x2A, 0x12,// $
0x23, 0x13, 0x08, 0x64, 0x62,// %
0x36, 0x49, 0x55, 0x22, 0x50,// &
0x00, 0x05, 0x03, 0x00, 0x00,// '
0x00, 0x1C, 0x22, 0x41, 0x00,// (
0x00, 0x41, 0x22, 0x1C, 0x00,// )
0x08, 0x2A, 0x1C, 0x2A, 0x08,// *
0x08, 0x08, 0x3E, 0x08, 0x08,// +
0x00, 0x50, 0x30, 0x00, 0x00,// ,
0x08, 0x08, 0x08, 0x08, 0x08,// -
0x00, 0x60, 0x60, 0x00, 0x00,// .
0x20, 0x10, 0x08, 0x04, 0x02,// /
0x3E, 0x51, 0x49, 0x45, 0x3E,// 0
0x00, 0x42, 0x7F, 0x40, 0x00,// 1
0x42, 0x61, 0x51, 0x49, 0x46,// 2
0x21, 0x41, 0x45, 0x4B, 0x31,// 3
0x18, 0x14, 0x12, 0x7F, 0x10,// 4
0x27, 0x45, 0x45, 0x45, 0x39,// 5
0x3C, 0x4A, 0x49, 0x49, 0x30,// 6
0x01, 0x71, 0x09, 0x05, 0x03,// 7
0x36, 0x49, 0x49, 0x49, 0x36,// 8
0x06, 0x49, 0x49, 0x29, 0x1E,// 9
0x00, 0x36, 0x36, 0x00, 0x00,// :
0x00, 0x56, 0x36, 0x00, 0x00,// ;
0x00, 0x08, 0x14, 0x22, 0x41,// <
0x14, 0x14, 0x14, 0x14, 0x14,// =
0x41, 0x22, 0x14, 0x08, 0x00,// >
0x02, 0x01, 0x51, 0x09, 0x06,// ?
0x32, 0x49, 0x79, 0x41, 0x3E,// @
0x7E, 0x11, 0x11, 0x11, 0x7E,// A
0x7F, 0x49, 0x49, 0x49, 0x36,// B
0x3E, 0x41, 0x41, 0x41, 0x22,// C
0x7F, 0x41, 0x41, 0x22, 0x1C,// D
0x7F, 0x49, 0x49, 0x49, 0x41,// E
0x7F, 0x09, 0x09, 0x01, 0x01,// F
0x3E, 0x41, 0x41, 0x51, 0x32,// G
0x7F, 0x08, 0x08, 0x08, 0x7F,// H
0x00, 0x41, 0x7F, 0x41, 0x00,// I
0x20, 0x40, 0x41, 0x3F, 0x01,// J
0x7F, 0x08, 0x14, 0x22, 0x41,// K
0x7F, 0x40, 0x40, 0x40, 0x40,// L
0x7F, 0x02, 0x04, 0x02, 0x7F,// M
0x7F, 0x04, 0x08, 0x10, 0x7F,// N
0x3E, 0x41, 0x41, 0x41, 0x3E,// O
0x7F, 0x09, 0x09, 0x09, 0x06,// P
0x3E, 0x41, 0x51, 0x21, 0x5E,// Q
0x7F, 0x09, 0x19, 0x29, 0x46,// R
0x46, 0x49, 0x49, 0x49, 0x31,// S
0x01, 0x01, 0x7F, 0x01, 0x01,// T
0x3F, 0x40, 0x40, 0x40, 0x3F,// U
0x1F, 0x20, 0x40, 0x20, 0x1F,// V
0x7F, 0x20, 0x18, 0x20, 0x7F,// W
0x63, 0x14, 0x08, 0x14, 0x63,// X
0x03, 0x04, 0x78, 0x04, 0x03,// Y
0x61, 0x51, 0x49, 0x45, 0x43,// Z
0x00, 0x00, 0x7F, 0x41, 0x41,// [
0x02, 0x04, 0x08, 0x10, 0x20,// "\"
0x41, 0x41, 0x7F, 0x00, 0x00,// ]
0x04, 0x02, 0x01, 0x02, 0x04,// ^
0x40, 0x40, 0x40, 0x40, 0x40,// _
0x00, 0x01, 0x02, 0x04, 0x00,// `
0x20, 0x54, 0x54, 0x54, 0x78,// a
0x7F, 0x48, 0x44, 0x44, 0x38,// b
0x38, 0x44, 0x44, 0x44, 0x20,// c
0x38, 0x44, 0x44, 0x48, 0x7F,// d
0x38, 0x54, 0x54, 0x54, 0x18,// e
0x08, 0x7E, 0x09, 0x01, 0x02,// f
0x08, 0x14, 0x54, 0x54, 0x3C,// g
0x7F, 0x08, 0x04, 0x04, 0x78,// h
0x00, 0x44, 0x7D, 0x40, 0x00,// i
0x20, 0x40, 0x44, 0x3D, 0x00,// j
0x00, 0x7F, 0x10, 0x28, 0x44,// k
0x00, 0x41, 0x7F, 0x40, 0x00,// l
0x7C, 0x04, 0x18, 0x04, 0x78,// m
0x7C, 0x08, 0x04, 0x04, 0x78,// n
0x38, 0x44, 0x44, 0x44, 0x38,// o
0x7C, 0x14, 0x14, 0x14, 0x08,// p
0x08, 0x14, 0x14, 0x18, 0x7C,// q
0x7C, 0x08, 0x04, 0x04, 0x08,// r
0x48, 0x54, 0x54, 0x54, 0x20,// s
0x04, 0x3F, 0x44, 0x40, 0x20,// t
0x3C, 0x40, 0x40, 0x20, 0x7C,// u
0x1C, 0x20, 0x40, 0x20, 0x1C,// v
0x3C, 0x40, 0x30, 0x40, 0x3C,// w
0x44, 0x28, 0x10, 0x28, 0x44,// x
0x0C, 0x50, 0x50, 0x50, 0x3C,// y
0x44, 0x64, 0x54, 0x4C, 0x44,// z
0x00, 0x08, 0x36, 0x41, 0x00,// {
0x00, 0x00, 0x7F, 0x00, 0x00,// |
0x00, 0x41, 0x36, 0x08, 0x00,// }
0x08, 0x08, 0x2A, 0x1C, 0x08,// ->
0x08, 0x1C, 0x2A, 0x08, 0x08 // <-
};
#endif
Please help!!!!
Thanks MagnusE