Subversion Repositories Projects

Compare Revisions

Ignore whitespace Rev 111 → Rev 112

/Transportables_Koptertool/trunk/V-0.1.1/lcd.c
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);
}
}