0,0 → 1,557 |
|
#define F_CPU 7372800UL |
#include <avr/io.h> |
#include <inttypes.h> |
#include <stdlib.h> |
#include <avr/pgmspace.h> |
#include <util/delay.h> |
|
#include "font8x6.h" |
#include "main.h" |
#include "lcd.h" |
|
#define DISP_W 128 |
#define DISP_H 64 |
// #define LCD_ORIENTATION 0 // 0 MJ Tasten unten / 4 Original Tasten oben |
|
|
uint8_t lcd_xpos; |
uint8_t lcd_ypos; |
//volatile uint8_t display_buffer[1024]; // Display-Puffer, weil nicht zurückgelesen werden kann |
//volatile uint16_t display_buffer_pointer; // Pointer auf das aktuell übertragene Byte |
//volatile uint8_t display_buffer_counter; // Hilfszähler zur Selektierung der Page |
//volatile uint8_t display_page_counter; // aktuelle Page-Nummer |
//volatile uint8_t display_mode; // Modus für State-Machine |
|
|
void send_byte (uint8_t data) |
{ |
clr_cs(); |
SPDR = data; |
while(!(SPSR & (1<<SPIF))); |
SPSR = SPSR; |
set_cs(); |
} |
|
void cls (void) |
{ |
uint16_t i,j; |
|
for (i=0;i<1024;i++) |
display_buffer[i] = 0x00; |
|
for (i=0;i<8;i++) |
{ |
clr_A0(); |
send_byte(0xB0+i); //1011xxxx |
send_byte(0x10); //00010000 |
// send_byte(0x04); //00000100 gedreht plus 4 Byte |
// send_byte(0x00); //00000000 |
send_byte(LCD_ORIENTATION); //00000000 |
|
|
set_A0(); |
for (j=0;j<128;j++) |
send_byte(0x00); |
} |
|
lcd_xpos = 0; |
lcd_ypos = 0; |
} |
|
void lcd_cls (void) |
{ |
cls(); |
} |
|
void wait_1ms(void) |
{ |
_delay_ms (1.0); |
} |
|
void wait_ms (uint16_t time) |
{ |
uint16_t i; |
|
for (i=0; i<time; i++) |
wait_1ms(); |
} |
|
void lcd_init (void) |
{ |
lcd_xpos = 0; |
lcd_ypos = 0; |
|
|
DDRB = 0xFF; |
|
SPCR = (1<<SPE)|(1<<MSTR)|(1<<CPHA)|(1<<CPOL)|(1<<SPR1); |
|
set_cs(); |
clr_reset(); |
wait_ms(10); |
set_reset(); |
|
clr_cs(); |
clr_A0(); |
|
send_byte(0x40); |
|
if (LCD_ORIENTATION == 0) |
{ |
send_byte(0xA1); // A1 normal A0 reverse(original) |
send_byte(0xC0); // C0 normal C8 reverse(original) |
} |
else |
{ |
send_byte(0xA0); // A1 normal A0 reverse(original) |
send_byte(0xC8); // C0 normal C8 reverse(original) |
} |
send_byte(0xA6); |
send_byte(0xA2); |
send_byte(0x2F); |
send_byte(0xF8); |
send_byte(0x00); |
send_byte(0x27); |
send_byte(0x81); |
send_byte(0x16); |
send_byte(0xAC); |
send_byte(0x00); |
send_byte(0xAF); |
|
cls(); |
|
} |
|
void set_adress (uint16_t adress, uint8_t data) |
{ |
uint8_t page; |
uint8_t column; |
|
page = adress >> 7; |
|
clr_A0(); |
send_byte(0xB0 + page); |
|
// column = (adress & 0x7F) + 4; Wenn gedreht |
// column = (adress & 0x7F); |
column = (adress & 0x7F) + LCD_ORIENTATION; |
|
send_byte(0x10 + (column >> 4)); |
send_byte(column & 0x0F); |
|
set_A0(); |
send_byte(data); |
} |
|
void scroll (void) |
{ |
uint16_t adress; |
|
for (adress=0;adress<896;adress++) |
{ |
display_buffer[adress] = display_buffer[adress+128]; |
set_adress(adress,display_buffer[adress]); |
} |
for (adress=896;adress<1024;adress++) |
{ |
display_buffer[adress] = 0; |
set_adress(adress,0); |
} |
} |
|
// |
// x,y = character-Pos. ! |
// |
// mode: 0=Overwrite, 1 = OR, 2 = XOR, 3 = AND, 4 = Delete |
void put_char (uint8_t x, uint8_t y, uint8_t c, uint8_t mode) |
{ |
uint8_t ch; |
uint8_t i; |
uint16_t adress; |
|
switch(c) |
{ |
case 'ä': |
c = 0x84; |
break; |
case 'ö': |
c = 0x94; |
break; |
case 'ü': |
c = 0x81; |
break; |
case 'Ä': |
c = 0x8E; |
break; |
case 'Ö': |
c = 0x99; |
break; |
case 'Ü': |
c = 0x9A; |
break; |
case 'ß': |
c = 0xE1; |
break; |
} |
|
adress = y*128 + x*6; |
adress &= 0x3FF; |
|
for (i=0;i<6;i++) |
{ |
ch = pgm_read_byte (&f8x6[0][0] + i + c * 6); |
|
switch (mode) |
{ |
case 0: |
display_buffer[adress+i] = ch; |
break; |
case 1: |
display_buffer[adress+i] |= ch; |
break; |
case 2: |
display_buffer[adress+i] ^= ch; |
break; |
case 3: |
display_buffer[adress+i] &= ch; |
break; |
case 4: |
display_buffer[adress+i] &= ~ch; |
break; |
} |
|
set_adress(adress+i,display_buffer[adress+i]); |
} |
} |
|
void new_line (void) |
{ |
lcd_ypos++; |
|
if (lcd_ypos > 7) |
{ |
scroll(); |
lcd_ypos = 7; |
} |
} |
|
|
void lcd_printp (const char *text, uint8_t mode) |
{ |
while (pgm_read_byte(text)) |
{ |
if (pgm_read_byte(text) > 0x1F) |
{ |
put_char(lcd_xpos,lcd_ypos,pgm_read_byte(text++),mode); |
|
lcd_xpos++; |
if (lcd_xpos > 20) |
{ |
lcd_xpos = 0; |
new_line(); |
} |
} |
else |
{ |
switch (pgm_read_byte(text)) |
{ |
case 0x0D: |
lcd_xpos = 0; |
break; |
case 0x0A: |
new_line(); |
break; |
} |
text++; |
} |
} |
} |
|
void lcd_print_atp (uint8_t x, uint8_t y, const char *text, uint8_t mode) |
{ |
lcd_xpos = x; |
lcd_ypos = y; |
lcd_printp (text, mode); |
} |
|
|
void lcd_print (uint8_t *text, uint8_t mode) |
{ |
while (*text) |
{ |
if (*text > 0x1F) |
{ |
put_char(lcd_xpos,lcd_ypos,*text++,mode); |
|
lcd_xpos++; |
if (lcd_xpos > 20) |
{ |
lcd_xpos = 0; |
new_line(); |
} |
} |
else |
{ |
switch (*text) |
{ |
case 0x0D: |
lcd_xpos = 0; |
break; |
case 0x0A: |
new_line(); |
break; |
} |
text++; |
} |
} |
} |
|
void lcd_print_at (uint8_t x, uint8_t y, uint8_t *text, uint8_t mode) |
{ |
lcd_xpos = x; |
lcd_ypos = y; |
lcd_print(text, mode); |
} |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
// + Plot (set one Pixel) |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
// mode: |
// 0=Clear, 1=Set, 2=XOR |
void lcd_plot (uint8_t xpos, uint8_t ypos, uint8_t mode) |
{ |
uint16_t adress; |
uint8_t mask; |
|
if ((xpos < 128) && (ypos < 64)) |
{ |
adress = (ypos/8) * 128 + xpos; // adress = 0/8 * 128 + 0 = 0 |
mask = 1<<(ypos & 0x07); // mask = 1<<0 = 1 |
|
adress &= 0x3FF; |
|
switch (mode) |
{ |
case 0: |
display_buffer[adress] &=~mask; |
break; |
case 1: |
display_buffer[adress] |= mask; |
break; |
case 2: |
display_buffer[adress] ^= mask; |
break; |
} |
|
set_adress(adress,display_buffer[adress]); |
} |
} |
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
// + Line (draws a line from x1,y1 to x2,y2 |
// + Based on Bresenham line-Algorithm |
// + found in the internet, modified by thkais 2007 |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|
void lcd_line(unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2, uint8_t mode) |
|
{ |
int x,y,count,xs,ys,xm,ym; |
|
x=(int)x1; |
y=(int)y1; |
xs=(int)x2 - (int)x1; |
ys=(int)y2 - (int)y1; |
if(xs < 0) |
xm= -1; |
else |
if(xs > 0) |
xm= 1; |
else |
xm= 0; |
if(ys < 0) |
ym= -1; |
else |
if(ys > 0) |
ym= 1; |
else |
ym= 0; |
if(xs < 0) |
xs= -xs; |
if(ys < 0) |
ys= -ys; |
|
lcd_plot((unsigned char)x, (unsigned char)y, mode); |
|
if(xs > ys) // Flat Line <45 degrees |
{ |
count= -(xs / 2); |
while(x != x2) |
{ |
count= count + ys; |
x= x + xm; |
if(count > 0) |
{ |
y= y + ym; |
count= count - xs; |
} |
lcd_plot((unsigned char)x, (unsigned char)y, mode); |
} |
} |
else // Line >=45 degrees |
{ |
count=- (ys / 2); |
while(y != y2) |
{ |
count= count + xs; |
y= y + ym; |
if(count > 0) |
{ |
x= x + xm; |
count= count - ys; |
} |
lcd_plot((unsigned char)x, (unsigned char)y, mode); |
} |
} |
} |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
// + Filled rectangle |
// + x1, y1 = upper left corner |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|
void lcd_frect (uint8_t x1, uint8_t y1, uint8_t widthx, uint8_t widthy, uint8_t mode) |
{ |
uint16_t x2, y2; |
uint16_t i; |
|
if (x1 >= DISP_W) |
x1 = DISP_W - 1; |
if (y1 >= DISP_H) |
y1 = DISP_H - 1; |
x2 = x1 + widthx; |
y2 = y1 + widthy; |
|
if (x2 > DISP_W) |
x2 = DISP_W; |
if (y2 > DISP_H) |
y2 = DISP_H; |
|
for (i=y1;i<=y2;i++) |
{ |
lcd_line(x1,i,x2,i,mode); |
} |
|
} |
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
// + outline of rectangle |
// + x1, y1 = upper left corner |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|
void lcd_rect (uint8_t x1, uint8_t y1, uint8_t widthx, uint8_t widthy, uint8_t mode) |
{ |
uint16_t x2, y2; |
|
if (x1 >= DISP_W) |
x1 = DISP_W - 1; |
if (y1 >= DISP_H) |
y1 = DISP_H - 1; |
x2 = x1 + widthx; |
y2 = y1 + widthy; |
|
if (x2 > DISP_W) |
x2 = DISP_W; |
if (y2 > DISP_H) |
y2 = DISP_H; |
|
lcd_line (x1, y1, x2, y1, mode); |
lcd_line (x2, y1, x2, y2, mode); |
lcd_line (x2, y2, x1, y2, mode); |
lcd_line (x1, y2, x1, y1, mode); |
} |
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
// + outline of a circle |
// + Based on Bresenham-algorithm found in wikipedia |
// + modified by thkais (2007) |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|
|
void draw_circle(int16_t x0, int16_t y0, int16_t radius, uint8_t mode) |
{ |
int16_t f = 1 - radius; |
int16_t ddF_x = 0; |
int16_t ddF_y = -2 * radius; |
int16_t x = 0; |
int16_t y = radius; |
|
lcd_plot(x0, y0 + radius, mode); |
lcd_plot(x0, y0 - radius, mode); |
lcd_plot(x0 + radius, y0, mode); |
lcd_plot(x0 - radius, y0, mode); |
|
while(x < y) |
{ |
if(f >= 0) |
{ |
y --; |
ddF_y += 2; |
f += ddF_y; |
} |
x ++; |
ddF_x += 2; |
f += ddF_x + 1; |
|
lcd_plot(x0 + x, y0 + y, mode); |
lcd_plot(x0 - x, y0 + y, mode); |
|
lcd_plot(x0 + x, y0 - y, mode); |
lcd_plot(x0 - x, y0 - y, mode); |
|
lcd_plot(x0 + y, y0 + x, mode); |
lcd_plot(x0 - y, y0 + x, mode); |
|
lcd_plot(x0 + y, y0 - x, mode); |
lcd_plot(x0 - y, y0 - x, mode); |
} |
} |
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
// + filled Circle |
// + modified circle-algorithm thkais (2007) |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|
void draw_fcircle(int16_t x0, int16_t y0, int16_t radius) |
{ |
int16_t f = 1 - radius; |
int16_t ddF_x = 0; |
int16_t ddF_y = -2 * radius; |
int16_t x = 0; |
int16_t y = radius; |
|
lcd_line(x0, y0 + radius,x0, y0 - radius,1); |
|
lcd_line(x0 + radius, y0,x0 - radius, y0,1); |
|
while(x < y) |
{ |
if(f >= 0) |
{ |
y--; |
ddF_y += 2; |
f += ddF_y; |
} |
x++; |
ddF_x += 2; |
f += ddF_x + 1; |
|
lcd_line(x0 + x, y0 + y,x0 - x, y0 + y,1); |
lcd_line(x0 + x, y0 - y,x0 - x, y0 - y,1); |
lcd_line(x0 + y, y0 + x,x0 - y, y0 + x,1); |
lcd_line(x0 + y, y0 - x,x0 - y, y0 - x,1); |
} |
} |