Blame |
Last modification |
View Log
| RSS feed
#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);
}
}