Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1920 - 1
/*****************************************************************************
2
 *   Copyright (C) 2009 Peter "woggle" Mack, mac@denich.net                  *
3
 *   - original LCD control by Thomas "thkais" Kaiser                        *
4
 *   - special number formating routines taken from C-OSD                    *
5
 *      from Claas Anders "CaScAdE" Rathje                                   *
6
 *   - some extension, ellipse and circ_line by Peter "woggle" Mack          *
7
 *                                                                           *
8
 *   This program is free software; you can redistribute it and/or modify    *
9
 *   it under the terms of the GNU General Public License as published by    *
10
 *   the Free Software Foundation; either version 2 of the License.          *
11
 *                                                                           *
12
 *   This program is distributed in the hope that it will be useful,         *
13
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
14
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
15
 *   GNU General Public License for more details.                            *
16
 *                                                                           *
17
 *   You should have received a copy of the GNU General Public License       *
18
 *   along with this program; if not, write to the                           *
19
 *   Free Software Foundation, Inc.,                                         *
20
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.               *
21
 *                                                                           *
22
 *****************************************************************************/
23
 
24
#include "../cpu.h"
25
#include <avr/io.h>
26
#include <avr/pgmspace.h>
27
#include <util/delay.h>
28
#include <stdlib.h>
29
#include <string.h>
30
#include <math.h>
31
 
32
#include "font8x6.h"
33
#include "Font8x8.h"
34
#include "../eeprom/eeprom.h"
35
#include "lcd.h"
36
#include "../main.h"
37
#include "../HAL_HW3_9.h"
38
 
39
 
40
#define DISP_W 128
41
#define DISP_H 64
42
 
43
#define DISP_BUFFER ((DISP_H * DISP_W) / 8)
44
#define LINE_BUFFER (((DISP_H/8) * DISP_W) / 8)
45
 
46
#define Jeti 1  // Jeti Routinen
47
 
48
volatile uint8_t display_buffer[DISP_BUFFER];	// Display-Puffer, weil nicht zurückgelesen werden kann
49
volatile uint8_t line_buffer[LINE_BUFFER];		// Zeilen-Puffer, weil nicht zurückgelesen werden kann
50
 
51
volatile uint16_t display_buffer_pointer;		// Pointer auf das aktuell übertragene Byte
52
volatile uint8_t display_buffer_counter;		// Hilfszähler zur Selektierung der Page
53
volatile uint8_t display_page_counter;			// aktuelle Page-Nummer
54
volatile uint8_t display_mode;					// Modus für State-Machine
55
volatile uint8_t LCD_ORIENTATION;
56
 
57
// DOG: 128 x 64 with 6x8 Font => 21 x 8
58
// MAX7456: 30 x 16
59
 
60
uint8_t lcd_xpos;
61
uint8_t lcd_ypos;
62
 
63
 
64
//-----------------------------------------------------------
65
void send_byte (uint8_t data)
66
{
67
	clr_cs ();
68
	SPDR = data;
69
	while (!(SPSR & (1<<SPIF)));
70
	//SPSR = SPSR;
71
	set_cs ();
72
}
73
 
74
 
75
//-----------------------------------------------------------
76
// * Writes one command byte
77
// * cmd           - the command byte
78
//
79
void lcd_command(uint8_t cmd)
80
{
81
//	LCD_SELECT();
82
//	LCD_CMD();
83
//	spi_write(cmd);
84
//	LCD_UNSELECT();
85
	clr_cs ();
86
	SPDR = cmd;
87
	while (!(SPSR & (1<<SPIF)));
88
	//SPSR = SPSR;
89
	set_cs ();
90
}
91
 
92
 
93
//-----------------------------------------------------------
94
void lcd_cls (void)
95
{
96
	uint16_t i, j;
97
 
98
//	memset (display_buffer, 0, 1024);
99
	for (i = 0; i < DISP_BUFFER; i++)
100
		display_buffer[i] = 0x00;
101
	for (i = 0; i < 8; i++)
102
	{
103
		clr_A0 ();
104
		send_byte (0xB0 + i);			//1011xxxx
105
		send_byte (0x10);				//00010000
106
//		send_byte(0x04);				//00000100 gedreht plus 4 Byte
107
//		send_byte(0x00);				//00000000
108
		send_byte (LCD_ORIENTATION);	//00000000
109
 
110
		set_A0 ();
111
		for (j = 0; j < 128; j++)
112
			send_byte (0x00);
113
	}
114
 
115
	lcd_xpos = 0;
116
	lcd_ypos = 0;
117
}
118
 
119
 
120
//-----------------------------------------------------------
121
void lcd_cls_line (uint8_t x, uint8_t y, uint8_t w)
122
{
123
	uint8_t lcd_width;
124
	uint8_t lcd_zpos;
125
	uint8_t i;
126
	uint8_t max = 21;
127
	lcd_width = w;
128
	lcd_xpos = x;
129
	lcd_ypos = y;
130
 
131
	if ((lcd_xpos + lcd_width) > max)
132
		lcd_width = max - lcd_xpos;
133
 
134
	lcd_zpos = lcd_xpos + lcd_width;
135
 
136
	for (i = lcd_xpos; i < lcd_zpos; i++)
137
		lcd_putc (i, lcd_ypos, 0x20, 0);
138
}
139
 
140
 
141
//-----------------------------------------------------------
142
void wait_1ms (void)
143
{
144
	_delay_ms (1);
145
}
146
 
147
 
148
//-----------------------------------------------------------
149
void wait_ms (uint16_t time)
150
{
151
	uint16_t i;
152
 
153
	for (i = 0; i < time; i++)
154
		wait_1ms ();
155
}
156
 
157
 
158
//-----------------------------------------------------------
159
void LCD_Init (uint8_t LCD_Mode)	// LCD_Mode 0= Default Mode 1= EEPROM-Parameter)
160
{
161
	lcd_xpos = 0;
162
	lcd_ypos = 0;
163
 
164
//	DDRB = 0xFF;
165
 
166
	// SPI max. speed
167
	// the DOGM128 lcd controller can work at 20 MHz
168
	SPCR = (1 << SPE) | (1 << MSTR) | (1 << CPHA) | (1 << CPOL);
169
	SPSR = (1 << SPI2X);
170
 
171
	set_cs ();
172
	clr_reset ();
173
	wait_ms (10);
174
	set_reset ();
175
 
176
	clr_cs ();
177
	clr_A0 ();
178
 
179
	send_byte (0x40);		//Display start line = 0
180
	if (LCD_Mode == 1)
181
	{
182
		if (LCD_ORIENTATION == 0)
183
		{
184
			send_byte (0xA1); // A1 normal A0 reverse(original)
185
			send_byte (0xC0); // C0 normal C8 reverse(original)
186
		}
187
		else
188
		{
189
			send_byte (0xA0); // A1 normal A0 reverse(original)
190
			send_byte (0xC8); // C0 normal C8 reverse(original)
191
		}
192
	}
193
	else
194
	{
195
		send_byte (0xA1); // A1 normal A0 reverse(original)
196
		send_byte (0xC0); // C0 normal C8 reverse(original)
197
	}
198
	if (LCD_Mode == 1)
199
	{
200
		if (Config.LCD_DisplayMode == 0)
201
			send_byte (0xA6);		//Display normal, not mirrored
202
		else
203
			send_byte (0xA7);		//Display reverse, not mirrored
204
	}
205
	else
206
		send_byte (0xA6);
207
 
208
 
209
	send_byte (0xA2);		//Set bias 1/9 (Duty 1/65)
210
	send_byte (0x2F);		//Booster, regulator and follower on
211
	send_byte (0xF8);		//Set internal booster to 4x
212
	send_byte (0x00);		//Set internal booster to 4x
213
	send_byte (0x27);		//resistor ratio set
214
 
215
	if (LCD_Mode == 1)
216
	{
217
		send_byte (0x81);		//Electronic volume	register set
218
		send_byte (Config.LCD_Kontrast);		//Electronic volume	register set
219
	}
220
	else
221
	{
222
		send_byte (0x81);
223
		send_byte (0x16);
224
	}
225
 
226
	send_byte (0xAC);		//Cursor
227
	send_byte (0x00);		//No Cursor
228
	send_byte (0xAF);		//No indicator
229
	if (Config.HWSound==0)
230
	  {
231
            if (LCD_Mode == 1)
232
            {
233
                    // Helligkeit setzen
234
                    OCR2A = Config.LCD_Helligkeit * 2.55;
235
            }
236
            else
237
            {
238
                    OCR2A = 255;
239
            }
240
	  }
241
	lcd_cls ();
242
}
243
 
244
 
245
//-----------------------------------------------------------
246
void set_adress (uint16_t adress, uint8_t data)
247
{
248
	uint8_t page;
249
	uint8_t column;
250
 
251
	page = adress >> 7;
252
 
253
	clr_A0 ();
254
	send_byte (0xB0 + page);
255
 
256
	column = (adress & 0x7F) + LCD_ORIENTATION;
257
 
258
	send_byte (0x10 + (column >> 4));
259
	send_byte (column & 0x0F);
260
 
261
	set_A0 ();
262
	send_byte (data);
263
}
264
 
265
 
266
//-----------------------------------------------------------
267
void scroll (void)
268
{
269
	uint16_t adress;
270
 
271
	for (adress = 0; adress < 896; adress++)
272
	{
273
		display_buffer[adress] = display_buffer[adress + 128];
274
		set_adress (adress, display_buffer[adress]);
275
	}
276
 
277
	for (adress = 896; adress < 1024; adress++)
278
	{
279
		display_buffer[adress] = 0;
280
		set_adress (adress, 0);
281
	}
282
}
283
 
284
 
285
//-----------------------------------------------------------
286
// sicher eine Zeile für die Statusanzeige
287
void copy_line (uint8_t y)
288
{
289
	uint8_t i;
290
	uint16_t adress;
291
 
292
	adress = y * 128 + 0 * 6;
293
	adress &= 0x3FF;
294
 
295
	for (i = 0; i < 6*21; i++)
296
	{
297
		line_buffer[i] = display_buffer[adress+i];
298
		set_adress (adress + i, display_buffer[adress + i]);
299
	}
300
}
301
 
302
 
303
//-----------------------------------------------------------
304
// holt gesicherte Zeile wieder zurück
305
void paste_line (uint8_t y)
306
{
307
	uint8_t i;
308
	uint16_t adress;
309
 
310
	adress = y * 128 + 0 * 6;
311
	adress &= 0x3FF;
312
 
313
	for (i = 0; i < 6*21; i++)
314
	{
315
		display_buffer[adress+i] =line_buffer[i];
316
		set_adress (adress + i, display_buffer[adress + i]);
317
	}
318
}
319
 
320
 
321
//-----------------------------------------------------------
322
void lcd_puts_at(uint8_t x, uint8_t y,const char *s, uint8_t mode )
323
{
324
	while (*s)
325
	{
326
		lcd_putc(x, y, *s++, mode);
327
		x++;
328
	}
329
 
330
}/* lcd_puts */
331
 
332
 
333
//-----------------------------------------------------------
334
void lcd_putc (uint8_t x, uint8_t y, uint8_t c, uint8_t mode)
335
{
336
	uint8_t ch;
337
	uint8_t i;
338
	uint16_t adress;
339
 
340
	if (mode == 2)
341
		lcd_frect ((x*6),(y*8),5,7,1); // invertierte Darstellung
342
 
343
	if (mode == 3)     lcd_putc_jeti (x, y, c,0);
344
	else
345
	  if (mode == 4)     lcd_putc_jeti (x, y, c,2);
346
	else
347
	 {
348
 
349
            switch (c)
350
            {	// ISO 8859-1
351
 
352
            case 0xc4:	// Ä
353
                    c = 0x01;
354
                    break;
355
 
356
            case 0xe4:	// ä
357
                    c = 0x02;
358
                    break;
359
 
360
            case 0xd6:	// Ö
361
                    c = 0x03;
362
                    break;
363
 
364
            case 0xf6:	// ö
365
                    c = 0x04;
366
                    break;
367
 
368
            case 0xdc:	// Ü
369
                    c = 0x05;
370
                    break;
371
 
372
            case 0xfc:	// ü
373
                    c = 0x06;
374
                    break;
375
 
376
            case 0xdf:	// ß
377
                    //c = 0x07;
378
                    c = 0x1e; // ° (used by Jeti)
379
                    break;
380
            }
381
 
382
            c &= 0x7f;
383
 
384
            adress = y * 128 + x * 6;
385
            adress &= 0x3FF;
386
 
387
            for (i = 0; i < 6; i++)
388
            {
389
                    ch = pgm_read_byte (&font8x6[0][0] + i + c * 6);
390
 
391
                    switch (mode)
392
                    {
393
 
394
                    case 0:
395
                            display_buffer[adress+i] = ch;
396
                            break;
397
 
398
                    case 1:
399
                            display_buffer[adress+i] |= ch;
400
                            break;
401
 
402
                    case 2:
403
                            display_buffer[adress+i] ^= ch;
404
                            break;
405
 
406
                    case 3:
407
                            display_buffer[adress+i] &= ch;
408
                            break;
409
 
410
                    case 4:
411
                            display_buffer[adress+i] &= ~ch;
412
                            break;
413
                    }
414
 
415
                    set_adress (adress + i, display_buffer[adress + i]);
416
              }
417
       }
418
}
419
 
420
 
421
#if Jeti
422
//-----------------------------------------------------------
423
void lcd_putc_jeti (uint8_t x, uint8_t y, uint8_t c, uint8_t mode)
424
{
425
	uint8_t ch;
426
	uint8_t i;
427
	uint16_t adress;
428
        if (mode == 2)
429
                lcd_frect ((x*8),(y*8),8,8,1); // invertierte Darstellung
430
	switch (c)
431
	{
432
 
433
	case 0x7e:
434
		c = 0x1a; // ->
435
		break;
436
 
437
	case 0x7f:
438
		c = 0x1b; // <-
439
		break;
440
 
441
	case 0xdf:
442
		c = 0xf8; // °
443
		break;
444
	}
445
 
446
	adress = y * 128 + x * 8;
447
	adress &= 0x3FF;
448
 
449
	for (i = 0; i < 8; i++)
450
	{
451
		ch = pgm_read_byte (&Font8x8[0][0] + i + c * 8);
452
 
453
		switch (mode)
454
		{
455
 
456
		case 0:
457
			display_buffer[adress+i] = ch;
458
			break;
459
 
460
		case 1:
461
			display_buffer[adress+i] |= ch;
462
			break;
463
 
464
		case 2:
465
			display_buffer[adress+i] ^= ch;
466
			break;
467
 
468
		case 3:
469
			display_buffer[adress+i] &= ch;
470
			break;
471
 
472
		case 4:
473
			display_buffer[adress+i] &= ~ch;
474
			break;
475
		}
476
 
477
		set_adress (adress + i, display_buffer[adress + i]);
478
	}
479
}
480
 
481
 
482
//-----------------------------------------------------------
483
void lcd_printpj (const char *text, uint8_t mode)
484
{
485
	while (pgm_read_byte(text))
486
	{
487
		switch (pgm_read_byte(text))
488
		{
489
 
490
		case 0x0D:
491
			lcd_xpos = 0;
492
			break;
493
 
494
		case 0x0A:
495
			new_line();
496
			break;
497
 
498
		default:
499
			lcd_putc_jeti (lcd_xpos, lcd_ypos, pgm_read_byte(text), mode);
500
			lcd_xpos++;
501
			if (lcd_xpos > 20)
502
			{
503
				lcd_xpos = 0;
504
				new_line ();
505
			}
506
			break;
507
		}
508
		text++;
509
	}
510
}
511
 
512
 
513
//-----------------------------------------------------------
514
void lcd_printpj_at (uint8_t x, uint8_t y, const char *text, uint8_t mode)
515
{
516
	lcd_xpos = x;
517
	lcd_ypos = y;
518
	lcd_printpj (text, mode);
519
}
520
#endif
521
 
522
 
523
//-----------------------------------------------------------
524
void new_line (void)
525
{
526
	lcd_ypos++;
527
 
528
	if (lcd_ypos > 7)
529
	{
530
		scroll ();
531
		lcd_ypos = 7;
532
	}
533
}
534
 
535
 
536
//-----------------------------------------------------------
537
void lcd_printpns (const char *text, uint8_t mode)
538
{
539
	while (pgm_read_byte(text))
540
	{
541
		switch (pgm_read_byte(text))
542
		{
543
 
544
		case 0x0D:
545
			lcd_xpos = 0;
546
			break;
547
 
548
		case 0x0A:
549
			new_line();
550
			break;
551
 
552
		default:
553
			lcd_putc (lcd_xpos, lcd_ypos, pgm_read_byte(text), mode);
554
			lcd_xpos++;
555
			if (lcd_xpos > 21)
556
			{
557
				lcd_xpos = 0;
558
//				new_line ();
559
			}
560
			break;
561
		}
562
		text++;
563
	}
564
}
565
 
566
 
567
//-----------------------------------------------------------
568
void lcd_printpns_at (uint8_t x, uint8_t y, const char *text, uint8_t mode)
569
{
570
	lcd_xpos = x;
571
	lcd_ypos = y;
572
	lcd_printpns (text, mode);
573
}
574
 
575
 
576
//-----------------------------------------------------------
577
void lcd_printp (const char *text, uint8_t mode)
578
{
579
	while (pgm_read_byte(text))
580
	{
581
		switch (pgm_read_byte(text))
582
		{
583
 
584
		case 0x0D:
585
			lcd_xpos = 0;
586
			break;
587
 
588
		case 0x0A:
589
			new_line();
590
			break;
591
 
592
		default:
593
			lcd_putc (lcd_xpos, lcd_ypos, pgm_read_byte(text), mode);
594
			lcd_xpos++;
595
			if (lcd_xpos > 21)
596
			{
597
				lcd_xpos = 0;
598
				new_line ();
599
			}
600
			break;
601
		}
602
		text++;
603
	}
604
}
605
 
606
 
607
//-----------------------------------------------------------
608
void lcd_printp_at (uint8_t x, uint8_t y, const char *text, uint8_t mode)
609
{
610
	lcd_xpos = x;
611
	lcd_ypos = y;
612
	lcd_printp (text, mode);
613
}
614
 
615
 
616
//-----------------------------------------------------------
617
void lcd_print (uint8_t *text, uint8_t mode)
618
{
619
	while (*text)
620
	{
621
		switch (*text)
622
		{
623
 
624
		case 0x0D:
625
			lcd_xpos = 0;
626
			break;
627
 
628
		case 0x0A:
629
			new_line();
630
			break;
631
 
632
		default:
633
			lcd_putc (lcd_xpos, lcd_ypos, *text, mode);
634
			lcd_xpos++;
635
			if (lcd_xpos > 21)
636
			{
637
				lcd_xpos = 0;
638
				new_line ();
639
			}
640
			break;
641
		}
642
		text++;
643
	}
644
}
645
 
646
 
647
//-----------------------------------------------------------
648
void lcd_print_at (uint8_t x, uint8_t y, uint8_t *text, uint8_t mode)
649
{
650
	lcd_xpos = x;
651
	lcd_ypos = y;
652
	lcd_print (text, mode);
653
}
654
 
655
 
656
//-----------------------------------------------------------
657
void print_display (uint8_t *text)
658
{
659
	while (*text)
660
	{
661
		lcd_putc (lcd_xpos, lcd_ypos, *text, 0);
662
		lcd_xpos++;
663
		if (lcd_xpos >= 20)
664
		{
665
			lcd_xpos = 0;
666
			new_line ();
667
		}
668
		text++;
669
	}
670
}
671
 
672
 
673
//-----------------------------------------------------------
674
void print_display_at (uint8_t x, uint8_t y, uint8_t *text)
675
{
676
	lcd_xpos = x;
677
	lcd_ypos = y;
678
	print_display (text);
679
}
680
 
681
 
682
//-----------------------------------------------------------
683
// + Plot (set one Pixel)
684
//-----------------------------------------------------------
685
// mode:
686
// 0=Clear, 1=Set, 2=XOR
687
void lcd_plot (uint8_t xpos, uint8_t ypos, uint8_t mode)
688
{
689
	uint16_t adress;
690
	uint8_t mask;
691
 
692
	if ((xpos < DISP_W) && (ypos < DISP_H))
693
	{
694
		adress = (ypos / 8) * DISP_W + xpos;		// adress = 0/8 * 128 + 0   = 0
695
		mask = 1 << (ypos & 0x07);					// mask = 1<<0 = 1
696
		adress &= DISP_BUFFER - 1;
697
		switch (mode)
698
		{
699
 
700
		case 0:
701
			display_buffer[adress] &= ~mask;
702
			break;
703
 
704
		case 1:
705
			display_buffer[adress] |= mask;
706
			break;
707
 
708
		case 2:
709
			display_buffer[adress] ^= mask;
710
			break;
711
		}
712
		set_adress (adress, display_buffer[adress]);
713
	}
714
}
715
 
716
 
717
//-----------------------------------------------------------
718
// + Line (draws a line from x1,y1 to x2,y2
719
// + Based on Bresenham line-Algorithm
720
// + found in the internet, modified by thkais 2007
721
//-----------------------------------------------------------
722
 
723
void lcd_line (unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2, uint8_t mode)
724
{
725
	int x, y, count, xs, ys, xm, ym;
726
 
727
	x = (int) x1;
728
	y = (int) y1;
729
	xs = (int) x2 - (int) x1;
730
	ys = (int) y2 - (int) y1;
731
	if (xs < 0)
732
		xm = -1;
733
	else
734
		if (xs > 0)
735
			xm = 1;
736
		else
737
			xm = 0;
738
	if (ys < 0)
739
		ym = -1;
740
	else
741
		if (ys > 0)
742
			ym = 1;
743
		else
744
			ym = 0;
745
	if (xs < 0)
746
		xs = -xs;
747
 
748
	if (ys < 0)
749
		ys = -ys;
750
 
751
	lcd_plot ((unsigned char) x, (unsigned char) y, mode);
752
 
753
	if (xs > ys) // Flat Line <45 degrees
754
	{
755
		count = -(xs / 2);
756
		while (x != x2)
757
		{
758
			count = count + ys;
759
			x = x + xm;
760
			if (count > 0)
761
			{
762
				y = y + ym;
763
				count = count - xs;
764
			}
765
			lcd_plot ((unsigned char) x, (unsigned char) y, mode);
766
		}
767
	}
768
	else // Line >=45 degrees
769
	{
770
		count =- (ys / 2);
771
		while (y != y2)
772
		{
773
			count = count + xs;
774
			y = y + ym;
775
			if (count > 0)
776
			{
777
				x = x + xm;
778
				count = count - ys;
779
			}
780
			lcd_plot ((unsigned char) x, (unsigned char) y, mode);
781
		}
782
	}
783
}
784
 
785
 
786
//-----------------------------------------------------------
787
// + Filled rectangle
788
// + x1, y1 = upper left corner
789
//-----------------------------------------------------------
790
 
791
void lcd_frect (uint8_t x1, uint8_t y1, uint8_t widthx, uint8_t widthy, uint8_t mode)
792
{
793
	uint16_t x2, y2;
794
	uint16_t i;
795
 
796
	if (x1 >= DISP_W)
797
		x1 = DISP_W - 1;
798
 
799
	if (y1 >= DISP_H)
800
		y1 = DISP_H - 1;
801
 
802
	x2 = x1 + widthx;
803
	y2 = y1 + widthy;
804
 
805
	if (x2 > DISP_W)
806
		x2 = DISP_W;
807
 
808
	if (y2 > DISP_H)
809
		y2 = DISP_H;
810
 
811
	for (i = y1; i <= y2; i++)
812
	{
813
		lcd_line (x1, i, x2, i, mode);
814
	}
815
}
816
 
817
 
818
//-----------------------------------------------------------
819
// + outline of rectangle
820
// + x1, y1 = upper left corner
821
//-----------------------------------------------------------
822
 
823
void lcd_rect (uint8_t x1, uint8_t y1, uint8_t widthx, uint8_t widthy, uint8_t mode)
824
{
825
	uint16_t x2, y2;
826
 
827
	if (x1 >= DISP_W)
828
		x1 = DISP_W - 1;
829
	if (y1 >= DISP_H)
830
		y1 = DISP_H - 1;
831
	x2 = x1 + widthx;
832
	y2 = y1 + widthy;
833
 
834
	if (x2 > DISP_W)
835
		x2 = DISP_W;
836
 
837
	if (y2 > DISP_H)
838
		y2 = DISP_H;
839
 
840
	lcd_line (x1, y1, x2, y1, mode);
841
	lcd_line (x2, y1, x2, y2, mode);
842
	lcd_line (x2, y2, x1, y2, mode);
843
	lcd_line (x1, y2, x1, y1, mode);
844
}
845
 
846
 
847
//-----------------------------------------------------------
848
// + outline of a circle
849
// + Based on Bresenham-algorithm found in wikipedia
850
// + modified by thkais (2007)
851
//-----------------------------------------------------------
852
 
853
void lcd_circle (int16_t x0, int16_t y0, int16_t radius, uint8_t mode)
854
{
855
	int16_t f = 1 - radius;
856
	int16_t ddF_x = 0;
857
	int16_t ddF_y = -2 * radius;
858
	int16_t x = 0;
859
	int16_t y = radius;
860
 
861
	lcd_plot (x0, y0 + radius, mode);
862
	lcd_plot (x0, y0 - radius, mode);
863
	lcd_plot (x0 + radius, y0, mode);
864
	lcd_plot (x0 - radius, y0, mode);
865
 
866
	while (x < y)
867
	{
868
		if (f >= 0)
869
		{
870
			y --;
871
			ddF_y += 2;
872
			f += ddF_y;
873
		}
874
		x ++;
875
		ddF_x += 2;
876
		f += ddF_x + 1;
877
 
878
		lcd_plot (x0 + x, y0 + y, mode);
879
		lcd_plot (x0 - x, y0 + y, mode);
880
 
881
		lcd_plot (x0 + x, y0 - y, mode);
882
		lcd_plot (x0 - x, y0 - y, mode);
883
 
884
		lcd_plot (x0 + y, y0 + x, mode);
885
		lcd_plot (x0 - y, y0 + x, mode);
886
 
887
		lcd_plot (x0 + y, y0 - x, mode);
888
		lcd_plot (x0 - y, y0 - x, mode);
889
	}
890
}
891
 
892
 
893
//-----------------------------------------------------------
894
// + filled Circle
895
// + modified circle-algorithm thkais (2007)
896
//-----------------------------------------------------------
897
 
898
void lcd_fcircle (int16_t x0, int16_t y0, int16_t radius,uint8_t mode)
899
{
900
	int16_t f = 1 - radius;
901
	int16_t ddF_x = 0;
902
	int16_t ddF_y = -2 * radius;
903
	int16_t x = 0;
904
	int16_t y = radius;
905
 
906
	lcd_line (x0, y0 + radius, x0, y0 - radius, mode);
907
 
908
	lcd_line (x0 + radius, y0, x0 - radius, y0, mode);
909
 
910
	while (x < y)
911
	{
912
		if (f >= 0)
913
		{
914
			y--;
915
			ddF_y += 2;
916
			f += ddF_y;
917
		}
918
		x++;
919
		ddF_x += 2;
920
		f += ddF_x + 1;
921
 
922
		lcd_line (x0 + x, y0 + y, x0 - x, y0 + y, mode);
923
		lcd_line (x0 + x, y0 - y, x0 - x, y0 - y, mode);
924
		lcd_line (x0 + y, y0 + x, x0 - y, y0 + x, mode);
925
		lcd_line (x0 + y, y0 - x, x0 - y, y0 - x, mode);
926
	}
927
}
928
 
929
 
930
//-----------------------------------------------------------
931
//
932
void lcd_circ_line (uint8_t x, uint8_t y, uint8_t r, uint16_t deg, uint8_t mode)
933
{
934
	uint8_t xc, yc;
935
	double deg_rad;
936
 
937
	deg_rad = (deg * M_PI) / 180.0;
938
 
939
	yc = y - (uint8_t) round (cos (deg_rad) * (double) r);
940
	xc = x + (uint8_t) round (sin (deg_rad) * (double) r);
941
	lcd_line (x, y, xc, yc, mode);
942
}
943
 
944
 
945
//-----------------------------------------------------------
946
//
947
void lcd_ellipse_line (uint8_t x, uint8_t y, uint8_t rx, uint8_t ry, uint16_t deg, uint8_t mode)
948
{
949
	uint8_t xc, yc;
950
	double deg_rad;
951
 
952
	deg_rad = (deg * M_PI) / 180.0;
953
 
954
	yc = y - (uint8_t) round (cos (deg_rad) * (double) ry);
955
	xc = x + (uint8_t) round (sin (deg_rad) * (double) rx);
956
	lcd_line (x, y, xc, yc, mode);
957
}
958
 
959
 
960
//-----------------------------------------------------------
961
//
962
void lcd_ellipse (int16_t x0, int16_t y0, int16_t rx, int16_t ry, uint8_t mode)
963
{
964
	const int16_t rx2 = rx * rx;
965
	const int16_t ry2 = ry * ry;
966
	int16_t F = round (ry2 - rx2 * ry + 0.25 * rx2);
967
	int16_t ddF_x = 0;
968
	int16_t ddF_y = 2 * rx2 * ry;
969
	int16_t x = 0;
970
	int16_t y = ry;
971
 
972
	lcd_plot (x0, y0 + ry, mode);
973
	lcd_plot (x0, y0 - ry, mode);
974
	lcd_plot (x0 + rx, y0, mode);
975
	lcd_plot (x0 - rx, y0, mode);
976
	// while ( 2*ry2*x < 2*rx2*y ) {  we can use ddF_x and ddF_y
977
	while (ddF_x < ddF_y)
978
	{
979
		if(F >= 0)
980
		{
981
			y     -= 1;		// south
982
			ddF_y -= 2 * rx2;
983
			F     -= ddF_y;
984
		}
985
		x     += 1;			// east
986
		ddF_x += 2 * ry2;
987
		F     += ddF_x + ry2;
988
		lcd_plot (x0 + x, y0 + y, mode);
989
		lcd_plot (x0 + x, y0 - y, mode);
990
		lcd_plot (x0 - x, y0 + y, mode);
991
		lcd_plot (x0 - x, y0 - y, mode);
992
	}
993
	F = round (ry2 * (x + 0.5) * (x + 0.5) + rx2 * (y - 1) * (y - 1) - rx2 * ry2);
994
	while(y > 0)
995
	{
996
		if(F <= 0)
997
		{
998
			x     += 1;		// east
999
			ddF_x += 2 * ry2;
1000
			F     += ddF_x;
1001
		}
1002
		y     -= 1;			// south
1003
		ddF_y -= 2 * rx2;
1004
		F     += rx2 - ddF_y;
1005
		lcd_plot (x0 + x, y0 + y, mode);
1006
		lcd_plot (x0 + x, y0 - y, mode);
1007
		lcd_plot (x0 - x, y0 + y, mode);
1008
		lcd_plot (x0 - x, y0 - y, mode);
1009
	}
1010
}
1011
 
1012
 
1013
//-----------------------------------------------------------
1014
//
1015
void lcd_ecircle (int16_t x0, int16_t y0, int16_t radius, uint8_t mode)
1016
{
1017
	lcd_ellipse (x0, y0, radius + 3, radius, mode);
1018
}
1019
 
1020
 
1021
//-----------------------------------------------------------
1022
//
1023
void lcd_ecirc_line (uint8_t x, uint8_t y, uint8_t r, uint16_t deg, uint8_t mode)
1024
{
1025
	lcd_ellipse_line(x, y, r + 3, r, deg, mode);
1026
}
1027
 
1028
 
1029
//-----------------------------------------------------------
1030
//
1031
void lcd_view_font (uint8_t page)
1032
{
1033
	int x;
1034
	int y;
1035
 
1036
	lcd_cls ();
1037
	lcd_printp (PSTR("  0123456789ABCDEF\r\n"), 0);
1038
	lcd_printpns_at (0, 7, PSTR(" \x1a    \x1b     Exit"), 0);
1039
 
1040
	lcd_ypos = 2;
1041
	for (y = page * 4 ; y < (page * 4 + 4); y++)
1042
	{
1043
		if (y < 10)
1044
		{
1045
			lcd_putc (0, lcd_ypos, '0' + y, 0);
1046
		}
1047
		else
1048
		{
1049
			lcd_putc (0, lcd_ypos, 'A' + y - 10, 0);
1050
		}
1051
		lcd_xpos = 2;
1052
		for (x = 0; x < 16; x++)
1053
		{
1054
			lcd_putc (lcd_xpos, lcd_ypos, y * 16 + x, 0);
1055
			lcd_xpos++;
1056
		}
1057
		lcd_ypos++;
1058
	}
1059
}
1060
 
1061
 
1062
//-----------------------------------------------------------
1063
uint8_t hdigit (uint8_t d)
1064
{
1065
	if (d < 10)
1066
	{
1067
		return '0' + d;
1068
	}
1069
	else
1070
	{
1071
		return 'A' + d - 10;
1072
	}
1073
}
1074
 
1075
 
1076
//-----------------------------------------------------------
1077
void lcd_print_hex_at (uint8_t x, uint8_t y, uint8_t h, uint8_t mode)
1078
{
1079
	lcd_xpos = x;
1080
	lcd_ypos = y;
1081
 
1082
	lcd_putc (lcd_xpos++, lcd_ypos, hdigit (h >> 4), mode);
1083
	lcd_putc (lcd_xpos, lcd_ypos, hdigit (h & 0x0f), mode);
1084
}
1085
 
1086
 
1087
//-----------------------------------------------------------
1088
void lcd_print_hex (uint8_t h, uint8_t mode)
1089
{
1090
//	lcd_xpos = x;
1091
//	lcd_ypos = y;
1092
 
1093
	lcd_putc (lcd_xpos++, lcd_ypos, hdigit (h >> 4), mode);
1094
	lcd_putc (lcd_xpos++, lcd_ypos, hdigit (h & 0x0f), mode);
1095
	lcd_putc (lcd_xpos++, lcd_ypos, ' ', mode);
1096
}
1097
 
1098
 
1099
//-----------------------------------------------------------
1100
void lcd_write_number_u (uint8_t number)
1101
{
1102
	uint8_t num = 100;
1103
	uint8_t started = 0;
1104
 
1105
	while (num > 0)
1106
	{
1107
		uint8_t b = number / num;
1108
		if (b > 0 || started || num == 1)
1109
		{
1110
			lcd_putc (lcd_xpos++, lcd_ypos, '0' + b, 0);
1111
			started = 1;
1112
		}
1113
		number -= b * num;
1114
 
1115
		num /= 10;
1116
	}
1117
}
1118
 
1119
 
1120
//-----------------------------------------------------------
1121
void lcd_write_number_u_at (uint8_t x, uint8_t y, uint8_t number)
1122
{
1123
	lcd_xpos = x;
1124
	lcd_ypos = y;
1125
	lcd_write_number_u (number);
1126
}
1127
 
1128
 
1129
//-----------------------------------------------------------
1130
// Write only some digits of a unsigned <number> at <x>/<y> to MAX7456 display memory
1131
// <num> represents the largest multiple of 10 that will still be displayable as
1132
// the first digit, so num = 10 will be 0-99 and so on
1133
// <pad> = 1 will cause blank spaced to be filled up with zeros e.g. 007 instead of   7
1134
//
1135
void write_ndigit_number_u (uint8_t x, uint8_t y, uint16_t number, int16_t length, uint8_t pad, uint8_t mode)
1136
{
1137
	char s[7];
1138
 
1139
	utoa(number, s, 10 );
1140
 
1141
	uint8_t len = strlen(s);
1142
 
1143
	if (length < len)
1144
	{
1145
		for (uint8_t i = 0; i < length; i++)
1146
		{
1147
			lcd_putc (x++, y, '*', mode);
1148
		}
1149
		return;
1150
	}
1151
 
1152
	for (uint8_t i = 0; i < length - len; i++)
1153
	{
1154
		if (pad==1)
1155
		{
1156
			lcd_putc (x++, y, '0', mode);
1157
		}
1158
		else
1159
		{
1160
			lcd_putc (x++, y, ' ', mode);
1161
		}
1162
	}
1163
	lcd_print_at(x, y, (uint8_t*)s, mode);
1164
}
1165
 
1166
//-----------------------------------------------------------
1167
// Write only some digits of a signed <number> at <x>/<y> to MAX7456 display memory
1168
// <num> represents the largest multiple of 10 that will still be displayable as
1169
// the first digit, so num = 10 will be 0-99 and so on
1170
// <pad> = 1 will cause blank spaced to be filled up with zeros e.g. 007 instead of   7
1171
//
1172
void write_ndigit_number_s (uint8_t x, uint8_t y, int16_t number, int16_t length, uint8_t pad, uint8_t mode)
1173
{
1174
	char s[7];
1175
 
1176
	itoa(number, s, 10 );
1177
 
1178
	uint8_t len = strlen(s);
1179
 
1180
	if (length < len)
1181
	{
1182
		for (uint8_t i = 0; i < length; i++)
1183
		{
1184
			lcd_putc (x++, y, '*', mode);
1185
		}
1186
		return;
1187
	}
1188
 
1189
	for (uint8_t i = 0; i < length - len; i++)
1190
	{
1191
		if (pad)
1192
		{
1193
			lcd_putc (x++, y, '0', mode);
1194
		}
1195
		else
1196
		{
1197
			lcd_putc (x++, y, ' ', mode);
1198
		}
1199
	}
1200
	lcd_print_at(x, y, (uint8_t*)s, mode);
1201
}
1202
 
1203
 
1204
//-----------------------------------------------------------
1205
// Write only some digits of a unsigned <number> at <x>/<y> to MAX7456 display memory
1206
// as /10th of the value
1207
// <num> represents the largest multiple of 10 that will still be displayable as
1208
// the first digit, so num = 10 will be 0-99 and so on
1209
// <pad> = 1 will cause blank spaced to be filled up with zeros e.g. 007 instead of   7
1210
//
1211
void write_ndigit_number_u_10th (uint8_t x, uint8_t y, uint16_t number, int16_t length, uint8_t pad, uint8_t mode)
1212
{
1213
	char s[7];
1214
 
1215
	itoa(number, s, 10 );
1216
 
1217
	uint8_t len = strlen(s);
1218
 
1219
	if (length < len)
1220
	{
1221
		for (uint8_t i = 0; i < length; i++)
1222
		{
1223
			lcd_putc (x++, y, '*', mode);
1224
		}
1225
		return;
1226
	}
1227
 
1228
	for (uint8_t i = 0; i < length - len; i++)
1229
	{
1230
		if (pad)
1231
		{
1232
			lcd_putc (x++, y, '0', mode);
1233
		}
1234
		else
1235
		{
1236
			lcd_putc (x++, y, ' ', mode);
1237
		}
1238
	}
1239
 
1240
	char rest = s[len - 1];
1241
 
1242
	s[len - 1] = 0;
1243
 
1244
	if (len == 1)
1245
	{
1246
		lcd_putc (x-1, y, '0', mode);
1247
	}
1248
	else if (len == 2 && s[0] == '-')
1249
	{
1250
		lcd_putc (x-1, y, '-', mode);
1251
		lcd_putc (x, y, '0', mode);
1252
	}
1253
	else
1254
	{
1255
		lcd_print_at(x, y, (uint8_t*)s, mode);
1256
	}
1257
	x += len - 1;
1258
	lcd_putc (x++, y, '.', mode);
1259
	lcd_putc (x++, y, rest, mode);
1260
}
1261
 
1262
 
1263
//-----------------------------------------------------------
1264
void write_ndigit_number_u_100th (uint8_t x, uint8_t y, uint16_t number, int16_t length, uint8_t pad)
1265
{
1266
	uint8_t num = 100;
1267
 
1268
	while (num > 0)
1269
	{
1270
		uint8_t b = number / num;
1271
 
1272
		if ((num / 10) == 1)
1273
		{
1274
			lcd_putc (x++, y, '.', 0);
1275
		}
1276
		lcd_putc (x++, y, '0' + b, 0);
1277
		number -= b * num;
1278
 
1279
		num /= 10;
1280
	}
1281
}
1282
 
1283
 
1284
//-----------------------------------------------------------
1285
// Write only some digits of a signed <number> at <x>/<y> to MAX7456 display memory
1286
// as /10th of the value
1287
// <num> represents the largest multiple of 10 that will still be displayable as
1288
// the first digit, so num = 10 will be 0-99 and so on
1289
// <pad> = 1 will cause blank spaced to be filled up with zeros e.g. 007 instead of   7
1290
//
1291
void write_ndigit_number_s_10th (uint8_t x, uint8_t y, int16_t number, int16_t length, uint8_t pad, uint8_t mode)
1292
{
1293
	char s[7];
1294
 
1295
	itoa (number, s, 10 );
1296
 
1297
	uint8_t len = strlen(s);
1298
 
1299
	if (length < len)
1300
	{
1301
		for (uint8_t i = 0; i < length; i++)
1302
		{
1303
			lcd_putc (x++, y, '*', mode);
1304
		}
1305
		return;
1306
	}
1307
 
1308
	for (uint8_t i = 0; i < length - len; i++)
1309
	{
1310
		if (pad)
1311
		{
1312
			lcd_putc (x++, y, '0', mode);
1313
		}
1314
		else
1315
		{
1316
			lcd_putc (x++, y, ' ', mode);
1317
		}
1318
	}
1319
 
1320
	char rest = s[len - 1];
1321
 
1322
	s[len - 1] = 0;
1323
 
1324
	if (len == 1)
1325
	{
1326
		lcd_putc (x-1, y, '0', mode);
1327
	}
1328
	else if (len == 2 && s[0] == '-')
1329
	{
1330
		lcd_putc (x-1, y, '-', mode);
1331
		lcd_putc (x, y, '0', mode);
1332
	}
1333
	else
1334
	{
1335
		lcd_print_at(x, y, (uint8_t*)s, mode);
1336
	}
1337
	x += len - 1;
1338
	lcd_putc (x++, y, '.', mode);
1339
	lcd_putc (x++, y, rest, mode);
1340
}
1341
 
1342
 
1343
//-----------------------------------------------------------
1344
// write <seconds> as human readable time at <x>/<y> to MAX7456 display mem
1345
//
1346
void write_time (uint8_t x, uint8_t y, uint16_t seconds)
1347
{
1348
	uint16_t min = seconds / 60;
1349
	seconds -= min * 60;
1350
	write_ndigit_number_u (x, y, min, 2, 0,0);
1351
	lcd_putc (x + 2, y, ':', 0);
1352
	write_ndigit_number_u (x + 3, y, seconds, 2, 1,0);
1353
}
1354
 
1355
 
1356
//-----------------------------------------------------------
1357
// wirte a <position> at <x>/<y> assuming it is a gps position for long-/latitude
1358
//
1359
void write_gps_pos (uint8_t x, uint8_t y, int32_t position)
1360
{
1361
	if (position < 0)
1362
	{
1363
		position ^= ~0;
1364
		position++;
1365
		lcd_putc (x++, y, '-', 0);
1366
	}
1367
	else
1368
	{
1369
		lcd_putc (x++, y, ' ', 0);
1370
	}
1371
	write_ndigit_number_u (x, y, (uint16_t) (position / (int32_t) 10000000), 3, 1,0);
1372
	lcd_putc (x + 3, y, '.', 0);
1373
	position = position - ((position / (int32_t) 10000000) * (int32_t) 10000000);
1374
	write_ndigit_number_u (x + 4, y, (uint16_t) (position / (int32_t) 1000), 4, 1,0);
1375
	position = position - ((uint16_t) (position / (int32_t) 1000) * (int32_t) 1000);
1376
	write_ndigit_number_u (x + 8, y, (uint16_t) position, 3, 1,0);
1377
	lcd_putc (x + 11, y, 0x1e, 0);	// degree symbol
1378
}
1379
 
1380
 
1381
//------------------------------------------------------------------------------------
1382
// Show PKT Baudrate at given position
1383
//
1384
 
1385
void show_baudrate (uint8_t x, uint8_t y, uint8_t Baudrate, uint8_t mode)
1386
 
1387
{
1388
  switch (Baudrate)
1389
  {
1390
      case Baud_2400:   lcd_printp_at (x, y, PSTR("2400"), mode);break;
1391
      case Baud_4800:   lcd_printp_at (x, y, PSTR("4800"), mode);break;
1392
      case Baud_9600:   lcd_printp_at (x, y, PSTR("9600"), mode);break;
1393
      case Baud_19200:  lcd_printp_at (x, y, PSTR("19200"), mode);break;
1394
      case Baud_38400:  lcd_printp_at (x, y, PSTR("38400"), mode);break;
1395
      case Baud_57600:  lcd_printp_at (x, y, PSTR("57600"), mode);break;
1396
      case Baud_115200: lcd_printp_at (x, y, PSTR("115200"), mode);break;
1397
        break;
1398
  }
1399
 
1400
 
1401
}
1402