Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

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