Blame |
Last modification |
View Log
| RSS feed
/*****************************************************************************
* Copyright (C) 2009 Peter "woggle" Mack, mac@denich.net *
* - original LCD control by Thomas "thkais" Kaiser *
* - special number formating routines taken from C-OSD *
* from Claas Anders "CaScAdE" Rathje *
* - some extension, ellipse and circ_line by Peter "woggle" Mack *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
*****************************************************************************/
#include "cpu.h"
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "font8x6.h"
#include "Font8x8.h"
#include "eeprom.h"
#include "lcd.h"
#include "HAL_HW3_9.h"
#define DISP_W 128
#define DISP_H 64
#define DISP_BUFFER ((DISP_H * DISP_W) / 8)
#define LINE_BUFFER (((DISP_H/8) * DISP_W) / 8)
#define Jeti 1 // Jeti Routinen
volatile uint8_t display_buffer
[DISP_BUFFER
]; // Display-Puffer, weil nicht zurückgelesen werden kann
volatile uint8_t line_buffer
[LINE_BUFFER
]; // Zeilen-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
volatile uint8_t LCD_ORIENTATION
;
// DOG: 128 x 64 with 6x8 Font => 21 x 8
// MAX7456: 30 x 16
uint8_t lcd_xpos
;
uint8_t lcd_ypos
;
//-----------------------------------------------------------
void send_byte
(uint8_t data
)
{
clr_cs
();
SPDR
= data
;
while (!(SPSR
& (1<<SPIF
)));
//SPSR = SPSR;
set_cs
();
}
//-----------------------------------------------------------
// * Writes one command byte
// * cmd - the command byte
//
void lcd_command
(uint8_t cmd
)
{
// LCD_SELECT();
// LCD_CMD();
// spi_write(cmd);
// LCD_UNSELECT();
clr_cs
();
SPDR
= cmd
;
while (!(SPSR
& (1<<SPIF
)));
//SPSR = SPSR;
set_cs
();
}
//-----------------------------------------------------------
void lcd_cls
(void)
{
uint16_t i
, j
;
// memset (display_buffer, 0, 1024);
for (i
= 0; i
< DISP_BUFFER
; 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_line
(uint8_t x
, uint8_t y
, uint8_t w
)
{
uint8_t lcd_width
;
uint8_t lcd_zpos
;
uint8_t i
;
uint8_t max
= 21;
lcd_width
= w
;
lcd_xpos
= x
;
lcd_ypos
= y
;
if ((lcd_xpos
+ lcd_width
) > max
)
lcd_width
= max
- lcd_xpos
;
lcd_zpos
= lcd_xpos
+ lcd_width
;
for (i
= lcd_xpos
; i
< lcd_zpos
; i
++)
lcd_putc
(i
, lcd_ypos
, 0x20, 0);
}
//-----------------------------------------------------------
void wait_1ms
(void)
{
_delay_ms
(1);
}
//-----------------------------------------------------------
void wait_ms
(uint16_t time)
{
uint16_t i
;
for (i
= 0; i
< time; i
++)
wait_1ms
();
}
//-----------------------------------------------------------
void LCD_Init
(uint8_t LCD_Mode
) // LCD_Mode 0= Default Mode 1= EEPROM-Parameter)
{
lcd_xpos
= 0;
lcd_ypos
= 0;
// DDRB = 0xFF;
// SPI max. speed
// the DOGM128 lcd controller can work at 20 MHz
SPCR
= (1 << SPE
) | (1 << MSTR
) | (1 << CPHA
) | (1 << CPOL
);
SPSR
= (1 << SPI2X
);
set_cs
();
clr_reset
();
wait_ms
(10);
set_reset
();
clr_cs
();
clr_A0
();
send_byte
(0x40); //Display start line = 0
if (LCD_Mode
== 1)
{
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)
}
}
else
{
send_byte
(0xA1); // A1 normal A0 reverse(original)
send_byte
(0xC0); // C0 normal C8 reverse(original)
}
if (LCD_Mode
== 1)
{
if (LCD_DisplayMode
== 0)
send_byte
(0xA6); //Display normal, not mirrored
else
send_byte
(0xA7); //Display reverse, not mirrored
}
else
send_byte
(0xA6);
send_byte
(0xA2); //Set bias 1/9 (Duty 1/65)
send_byte
(0x2F); //Booster, regulator and follower on
send_byte
(0xF8); //Set internal booster to 4x
send_byte
(0x00); //Set internal booster to 4x
send_byte
(0x27); //resistor ratio set
if (LCD_Mode
== 1)
{
send_byte
(0x81); //Electronic volume register set
send_byte
(LCD_Kontrast
); //Electronic volume register set
}
else
{
send_byte
(0x81);
send_byte
(0x16);
}
send_byte
(0xAC); //Cursor
send_byte
(0x00); //No Cursor
send_byte
(0xAF); //No indicator
if (LCD_Mode
== 1)
{
// Helligkeit setzen
OCR2A
= LCD_Helligkeit
* 2.55;
}
else
{
OCR2A
= 255;
}
lcd_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) + 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);
}
}
//-----------------------------------------------------------
// sicher eine Zeile für die Statusanzeige
void copy_line
(uint8_t y
)
{
uint8_t i
;
uint16_t adress
;
adress
= y
* 128 + 0 * 6;
adress
&= 0x3FF;
for (i
= 0; i
< 6*21; i
++)
{
line_buffer
[i
] = display_buffer
[adress
+i
];
set_adress
(adress
+ i
, display_buffer
[adress
+ i
]);
}
}
//-----------------------------------------------------------
// holt gesicherte Zeile wieder zurück
void paste_line
(uint8_t y
)
{
uint8_t i
;
uint16_t adress
;
adress
= y
* 128 + 0 * 6;
adress
&= 0x3FF;
for (i
= 0; i
< 6*21; i
++)
{
display_buffer
[adress
+i
] =line_buffer
[i
];
set_adress
(adress
+ i
, display_buffer
[adress
+ i
]);
}
}
//-----------------------------------------------------------
void lcd_puts_at
(uint8_t x
, uint8_t y
,const char *s
, uint8_t mode
)
{
while (*s
)
{
lcd_putc
(x
, y
, *s
++, mode
);
x
++;
}
}/* lcd_puts */
//-----------------------------------------------------------
void lcd_putc
(uint8_t x
, uint8_t y
, uint8_t c
, uint8_t mode
)
{
uint8_t ch
;
uint8_t i
;
uint16_t adress
;
if (mode
== 2)
lcd_frect
((x
*6),(y
*8),5,7,1); // invertierte Darstellung
if (mode
== 3) lcd_putc_jeti
(x
, y
, c
,0);
else
if (mode
== 4) lcd_putc_jeti
(x
, y
, c
,2);
else
{
switch (c
)
{ // ISO 8859-1
case 0xc4: // Ä
c
= 0x01;
break;
case 0xe4: // ä
c
= 0x02;
break;
case 0xd6: // Ö
c
= 0x03;
break;
case 0xf6: // ö
c
= 0x04;
break;
case 0xdc: // Ü
c
= 0x05;
break;
case 0xfc: // ü
c
= 0x06;
break;
case 0xdf: // ß
//c = 0x07;
c
= 0x1e; // ° (used by Jeti)
break;
}
c
&= 0x7f;
adress
= y
* 128 + x
* 6;
adress
&= 0x3FF;
for (i
= 0; i
< 6; i
++)
{
ch
= pgm_read_byte
(&font8x6
[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
]);
}
}
}
#if Jeti
//-----------------------------------------------------------
void lcd_putc_jeti
(uint8_t x
, uint8_t y
, uint8_t c
, uint8_t mode
)
{
uint8_t ch
;
uint8_t i
;
uint16_t adress
;
if (mode
== 2)
lcd_frect
((x
*8),(y
*8),8,8,1); // invertierte Darstellung
switch (c
)
{
case 0x7e:
c
= 0x1a; // ->
break;
case 0x7f:
c
= 0x1b; // <-
break;
case 0xdf:
c
= 0xf8; // °
break;
}
adress
= y
* 128 + x
* 8;
adress
&= 0x3FF;
for (i
= 0; i
< 8; i
++)
{
ch
= pgm_read_byte
(&Font8x8
[0][0] + i
+ c
* 8);
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 lcd_printpj
(const char *text
, uint8_t mode
)
{
while (pgm_read_byte
(text
))
{
switch (pgm_read_byte
(text
))
{
case 0x0D:
lcd_xpos
= 0;
break;
case 0x0A:
new_line
();
break;
default:
lcd_putc_jeti
(lcd_xpos
, lcd_ypos
, pgm_read_byte
(text
), mode
);
lcd_xpos
++;
if (lcd_xpos
> 20)
{
lcd_xpos
= 0;
new_line
();
}
break;
}
text
++;
}
}
//-----------------------------------------------------------
void lcd_printpj_at
(uint8_t x
, uint8_t y
, const char *text
, uint8_t mode
)
{
lcd_xpos
= x
;
lcd_ypos
= y
;
lcd_printpj
(text
, mode
);
}
#endif
//-----------------------------------------------------------
void new_line
(void)
{
lcd_ypos
++;
if (lcd_ypos
> 7)
{
scroll
();
lcd_ypos
= 7;
}
}
//-----------------------------------------------------------
void lcd_printpns
(const char *text
, uint8_t mode
)
{
while (pgm_read_byte
(text
))
{
switch (pgm_read_byte
(text
))
{
case 0x0D:
lcd_xpos
= 0;
break;
case 0x0A:
new_line
();
break;
default:
lcd_putc
(lcd_xpos
, lcd_ypos
, pgm_read_byte
(text
), mode
);
lcd_xpos
++;
if (lcd_xpos
> 21)
{
lcd_xpos
= 0;
// new_line ();
}
break;
}
text
++;
}
}
//-----------------------------------------------------------
void lcd_printpns_at
(uint8_t x
, uint8_t y
, const char *text
, uint8_t mode
)
{
lcd_xpos
= x
;
lcd_ypos
= y
;
lcd_printpns
(text
, mode
);
}
//-----------------------------------------------------------
void lcd_printp
(const char *text
, uint8_t mode
)
{
while (pgm_read_byte
(text
))
{
switch (pgm_read_byte
(text
))
{
case 0x0D:
lcd_xpos
= 0;
break;
case 0x0A:
new_line
();
break;
default:
lcd_putc
(lcd_xpos
, lcd_ypos
, pgm_read_byte
(text
), mode
);
lcd_xpos
++;
if (lcd_xpos
> 21)
{
lcd_xpos
= 0;
new_line
();
}
break;
}
text
++;
}
}
//-----------------------------------------------------------
void lcd_printp_at
(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
)
{
switch (*text
)
{
case 0x0D:
lcd_xpos
= 0;
break;
case 0x0A:
new_line
();
break;
default:
lcd_putc
(lcd_xpos
, lcd_ypos
, *text
, mode
);
lcd_xpos
++;
if (lcd_xpos
> 21)
{
lcd_xpos
= 0;
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
);
}
//-----------------------------------------------------------
void print_display
(uint8_t *text
)
{
while (*text
)
{
lcd_putc
(lcd_xpos
, lcd_ypos
, *text
, 0);
lcd_xpos
++;
if (lcd_xpos
>= 20)
{
lcd_xpos
= 0;
new_line
();
}
text
++;
}
}
//-----------------------------------------------------------
void print_display_at
(uint8_t x
, uint8_t y
, uint8_t *text
)
{
lcd_xpos
= x
;
lcd_ypos
= y
;
print_display
(text
);
}
//-----------------------------------------------------------
// + 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
< DISP_W
) && (ypos
< DISP_H
))
{
adress
= (ypos
/ 8) * DISP_W
+ xpos
; // adress = 0/8 * 128 + 0 = 0
mask
= 1 << (ypos
& 0x07); // mask = 1<<0 = 1
adress
&= DISP_BUFFER
- 1;
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 lcd_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 lcd_fcircle
(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_line
(x0
, y0
+ radius
, x0
, y0
- radius
, mode
);
lcd_line
(x0
+ radius
, y0
, 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_line
(x0
+ x
, y0
+ y
, x0
- x
, y0
+ y
, mode
);
lcd_line
(x0
+ x
, y0
- y
, x0
- x
, y0
- y
, mode
);
lcd_line
(x0
+ y
, y0
+ x
, x0
- y
, y0
+ x
, mode
);
lcd_line
(x0
+ y
, y0
- x
, x0
- y
, y0
- x
, mode
);
}
}
//-----------------------------------------------------------
//
void lcd_circ_line
(uint8_t x
, uint8_t y
, uint8_t r
, uint16_t deg
, uint8_t mode
)
{
uint8_t xc
, yc
;
double deg_rad
;
deg_rad
= (deg
* M_PI
) / 180.0;
yc
= y
- (uint8_t) round
(cos (deg_rad
) * (double) r
);
xc
= x
+ (uint8_t) round
(sin (deg_rad
) * (double) r
);
lcd_line
(x
, y
, xc
, yc
, mode
);
}
//-----------------------------------------------------------
//
void lcd_ellipse_line
(uint8_t x
, uint8_t y
, uint8_t rx
, uint8_t ry
, uint16_t deg
, uint8_t mode
)
{
uint8_t xc
, yc
;
double deg_rad
;
deg_rad
= (deg
* M_PI
) / 180.0;
yc
= y
- (uint8_t) round
(cos (deg_rad
) * (double) ry
);
xc
= x
+ (uint8_t) round
(sin (deg_rad
) * (double) rx
);
lcd_line
(x
, y
, xc
, yc
, mode
);
}
//-----------------------------------------------------------
//
void lcd_ellipse
(int16_t x0
, int16_t y0
, int16_t rx
, int16_t ry
, uint8_t mode
)
{
const int16_t rx2
= rx
* rx
;
const int16_t ry2
= ry
* ry
;
int16_t F
= round
(ry2
- rx2
* ry
+ 0.25 * rx2
);
int16_t ddF_x
= 0;
int16_t ddF_y
= 2 * rx2
* ry
;
int16_t x
= 0;
int16_t y
= ry
;
lcd_plot
(x0
, y0
+ ry
, mode
);
lcd_plot
(x0
, y0
- ry
, mode
);
lcd_plot
(x0
+ rx
, y0
, mode
);
lcd_plot
(x0
- rx
, y0
, mode
);
// while ( 2*ry2*x < 2*rx2*y ) { we can use ddF_x and ddF_y
while (ddF_x
< ddF_y
)
{
if(F
>= 0)
{
y
-= 1; // south
ddF_y
-= 2 * rx2
;
F
-= ddF_y
;
}
x
+= 1; // east
ddF_x
+= 2 * ry2
;
F
+= ddF_x
+ ry2
;
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
);
}
F
= round
(ry2
* (x
+ 0.5) * (x
+ 0.5) + rx2
* (y
- 1) * (y
- 1) - rx2
* ry2
);
while(y
> 0)
{
if(F
<= 0)
{
x
+= 1; // east
ddF_x
+= 2 * ry2
;
F
+= ddF_x
;
}
y
-= 1; // south
ddF_y
-= 2 * rx2
;
F
+= rx2
- ddF_y
;
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
);
}
}
//-----------------------------------------------------------
//
void lcd_ecircle
(int16_t x0
, int16_t y0
, int16_t radius
, uint8_t mode
)
{
lcd_ellipse
(x0
, y0
, radius
+ 3, radius
, mode
);
}
//-----------------------------------------------------------
//
void lcd_ecirc_line
(uint8_t x
, uint8_t y
, uint8_t r
, uint16_t deg
, uint8_t mode
)
{
lcd_ellipse_line
(x
, y
, r
+ 3, r
, deg
, mode
);
}
//-----------------------------------------------------------
//
void lcd_view_font
(uint8_t page
)
{
int x
;
int y
;
lcd_cls
();
lcd_printp
(PSTR
(" 0123456789ABCDEF\r\n"), 0);
lcd_printpns_at
(0, 7, PSTR
(" \x1a \x1b Exit"), 0);
lcd_ypos
= 2;
for (y
= page
* 4 ; y
< (page
* 4 + 4); y
++)
{
if (y
< 10)
{
lcd_putc
(0, lcd_ypos
, '0' + y
, 0);
}
else
{
lcd_putc
(0, lcd_ypos
, 'A' + y
- 10, 0);
}
lcd_xpos
= 2;
for (x
= 0; x
< 16; x
++)
{
lcd_putc
(lcd_xpos
, lcd_ypos
, y
* 16 + x
, 0);
lcd_xpos
++;
}
lcd_ypos
++;
}
}
//-----------------------------------------------------------
uint8_t hdigit
(uint8_t d
)
{
if (d
< 10)
{
return '0' + d
;
}
else
{
return 'A' + d
- 10;
}
}
//-----------------------------------------------------------
void lcd_print_hex_at
(uint8_t x
, uint8_t y
, uint8_t h
, uint8_t mode
)
{
lcd_xpos
= x
;
lcd_ypos
= y
;
lcd_putc
(lcd_xpos
++, lcd_ypos
, hdigit
(h
>> 4), mode
);
lcd_putc
(lcd_xpos
, lcd_ypos
, hdigit
(h
& 0x0f), mode
);
}
//-----------------------------------------------------------
void lcd_print_hex
(uint8_t h
, uint8_t mode
)
{
// lcd_xpos = x;
// lcd_ypos = y;
lcd_putc
(lcd_xpos
++, lcd_ypos
, hdigit
(h
>> 4), mode
);
lcd_putc
(lcd_xpos
++, lcd_ypos
, hdigit
(h
& 0x0f), mode
);
lcd_putc
(lcd_xpos
++, lcd_ypos
, ' ', mode
);
}
//-----------------------------------------------------------
void lcd_write_number_u
(uint8_t number
)
{
uint8_t num
= 100;
uint8_t started
= 0;
while (num
> 0)
{
uint8_t b
= number
/ num
;
if (b
> 0 || started
|| num
== 1)
{
lcd_putc
(lcd_xpos
++, lcd_ypos
, '0' + b
, 0);
started
= 1;
}
number
-= b
* num
;
num
/= 10;
}
}
//-----------------------------------------------------------
void lcd_write_number_u_at
(uint8_t x
, uint8_t y
, uint8_t number
)
{
lcd_xpos
= x
;
lcd_ypos
= y
;
lcd_write_number_u
(number
);
}
//-----------------------------------------------------------
// Write only some digits of a unsigned <number> at <x>/<y> to MAX7456 display memory
// <num> represents the largest multiple of 10 that will still be displayable as
// the first digit, so num = 10 will be 0-99 and so on
// <pad> = 1 will cause blank spaced to be filled up with zeros e.g. 007 instead of 7
//
void write_ndigit_number_u
(uint8_t x
, uint8_t y
, uint16_t number
, int16_t length
, uint8_t pad
, uint8_t mode
)
{
char s
[7];
utoa
(number
, s
, 10 );
uint8_t len
= strlen(s
);
if (length
< len
)
{
for (uint8_t i
= 0; i
< length
; i
++)
{
lcd_putc
(x
++, y
, '*', mode
);
}
return;
}
for (uint8_t i
= 0; i
< length
- len
; i
++)
{
if (pad
==1)
{
lcd_putc
(x
++, y
, '0', mode
);
}
else
{
lcd_putc
(x
++, y
, ' ', mode
);
}
}
lcd_print_at
(x
, y
, (uint8_t*)s
, mode
);
}
//-----------------------------------------------------------
// Write only some digits of a signed <number> at <x>/<y> to MAX7456 display memory
// <num> represents the largest multiple of 10 that will still be displayable as
// the first digit, so num = 10 will be 0-99 and so on
// <pad> = 1 will cause blank spaced to be filled up with zeros e.g. 007 instead of 7
//
void write_ndigit_number_s
(uint8_t x
, uint8_t y
, int16_t number
, int16_t length
, uint8_t pad
, uint8_t mode
)
{
char s
[7];
itoa(number
, s
, 10 );
uint8_t len
= strlen(s
);
if (length
< len
)
{
for (uint8_t i
= 0; i
< length
; i
++)
{
lcd_putc
(x
++, y
, '*', mode
);
}
return;
}
for (uint8_t i
= 0; i
< length
- len
; i
++)
{
if (pad
)
{
lcd_putc
(x
++, y
, '0', mode
);
}
else
{
lcd_putc
(x
++, y
, ' ', mode
);
}
}
lcd_print_at
(x
, y
, (uint8_t*)s
, mode
);
}
//-----------------------------------------------------------
// Write only some digits of a unsigned <number> at <x>/<y> to MAX7456 display memory
// as /10th of the value
// <num> represents the largest multiple of 10 that will still be displayable as
// the first digit, so num = 10 will be 0-99 and so on
// <pad> = 1 will cause blank spaced to be filled up with zeros e.g. 007 instead of 7
//
void write_ndigit_number_u_10th
(uint8_t x
, uint8_t y
, uint16_t number
, int16_t length
, uint8_t pad
, uint8_t mode
)
{
char s
[7];
itoa(number
, s
, 10 );
uint8_t len
= strlen(s
);
if (length
< len
)
{
for (uint8_t i
= 0; i
< length
; i
++)
{
lcd_putc
(x
++, y
, '*', mode
);
}
return;
}
for (uint8_t i
= 0; i
< length
- len
; i
++)
{
if (pad
)
{
lcd_putc
(x
++, y
, '0', mode
);
}
else
{
lcd_putc
(x
++, y
, ' ', mode
);
}
}
char rest
= s
[len
- 1];
s
[len
- 1] = 0;
if (len
== 1)
{
lcd_putc
(x
-1, y
, '0', mode
);
}
else if (len
== 2 && s
[0] == '-')
{
lcd_putc
(x
-1, y
, '-', mode
);
lcd_putc
(x
, y
, '0', mode
);
}
else
{
lcd_print_at
(x
, y
, (uint8_t*)s
, mode
);
}
x
+= len
- 1;
lcd_putc
(x
++, y
, '.', mode
);
lcd_putc
(x
++, y
, rest
, mode
);
}
//-----------------------------------------------------------
void write_ndigit_number_u_100th
(uint8_t x
, uint8_t y
, uint16_t number
, int16_t length
, uint8_t pad
)
{
uint8_t num
= 100;
while (num
> 0)
{
uint8_t b
= number
/ num
;
if ((num
/ 10) == 1)
{
lcd_putc
(x
++, y
, '.', 0);
}
lcd_putc
(x
++, y
, '0' + b
, 0);
number
-= b
* num
;
num
/= 10;
}
}
//-----------------------------------------------------------
// Write only some digits of a signed <number> at <x>/<y> to MAX7456 display memory
// as /10th of the value
// <num> represents the largest multiple of 10 that will still be displayable as
// the first digit, so num = 10 will be 0-99 and so on
// <pad> = 1 will cause blank spaced to be filled up with zeros e.g. 007 instead of 7
//
void write_ndigit_number_s_10th
(uint8_t x
, uint8_t y
, int16_t number
, int16_t length
, uint8_t pad
, uint8_t mode
)
{
char s
[7];
itoa (number
, s
, 10 );
uint8_t len
= strlen(s
);
if (length
< len
)
{
for (uint8_t i
= 0; i
< length
; i
++)
{
lcd_putc
(x
++, y
, '*', mode
);
}
return;
}
for (uint8_t i
= 0; i
< length
- len
; i
++)
{
if (pad
)
{
lcd_putc
(x
++, y
, '0', mode
);
}
else
{
lcd_putc
(x
++, y
, ' ', mode
);
}
}
char rest
= s
[len
- 1];
s
[len
- 1] = 0;
if (len
== 1)
{
lcd_putc
(x
-1, y
, '0', mode
);
}
else if (len
== 2 && s
[0] == '-')
{
lcd_putc
(x
-1, y
, '-', mode
);
lcd_putc
(x
, y
, '0', mode
);
}
else
{
lcd_print_at
(x
, y
, (uint8_t*)s
, mode
);
}
x
+= len
- 1;
lcd_putc
(x
++, y
, '.', mode
);
lcd_putc
(x
++, y
, rest
, mode
);
}
//-----------------------------------------------------------
// write <seconds> as human readable time at <x>/<y> to MAX7456 display mem
//
void write_time
(uint8_t x
, uint8_t y
, uint16_t seconds
)
{
uint16_t min
= seconds
/ 60;
seconds
-= min
* 60;
write_ndigit_number_u
(x
, y
, min
, 2, 0,0);
lcd_putc
(x
+ 2, y
, ':', 0);
write_ndigit_number_u
(x
+ 3, y
, seconds
, 2, 1,0);
}
//-----------------------------------------------------------
// wirte a <position> at <x>/<y> assuming it is a gps position for long-/latitude
//
void write_gps_pos
(uint8_t x
, uint8_t y
, int32_t position
)
{
if (position
< 0)
{
position
^= ~
0;
position
++;
lcd_putc
(x
++, y
, '-', 0);
}
else
{
lcd_putc
(x
++, y
, ' ', 0);
}
write_ndigit_number_u
(x
, y
, (uint16_t) (position
/ (int32_t) 10000000), 3, 1,0);
lcd_putc
(x
+ 3, y
, '.', 0);
position
= position
- ((position
/ (int32_t) 10000000) * (int32_t) 10000000);
write_ndigit_number_u
(x
+ 4, y
, (uint16_t) (position
/ (int32_t) 1000), 4, 1,0);
position
= position
- ((uint16_t) (position
/ (int32_t) 1000) * (int32_t) 1000);
write_ndigit_number_u
(x
+ 8, y
, (uint16_t) position
, 3, 1,0);
lcd_putc
(x
+ 11, y
, 0x1e, 0); // degree symbol
}