Subversion Repositories Projects

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1734 - 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 1  // 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
        if (mode == 3)     lcd_putc_jeti (x, y, c,0);
342
        else
343
          if (mode == 4)     lcd_putc_jeti (x, y, c,2);
344
        else
345
         {
346
 
347
            switch (c)
348
            {   // ISO 8859-1
349
 
350
            case 0xc4:  // Ä
351
                    c = 0x01;
352
                    break;
353
 
354
            case 0xe4:  // ä
355
                    c = 0x02;
356
                    break;
357
 
358
            case 0xd6:  // Ö
359
                    c = 0x03;
360
                    break;
361
 
362
            case 0xf6:  // ö
363
                    c = 0x04;
364
                    break;
365
 
366
            case 0xdc:  // Ü
367
                    c = 0x05;
368
                    break;
369
 
370
            case 0xfc:  // ü
371
                    c = 0x06;
372
                    break;
373
 
374
            case 0xdf:  // ß
375
                    //c = 0x07;
376
                    c = 0x1e; // ° (used by Jeti)
377
                    break;
378
            }
379
 
380
            c &= 0x7f;
381
 
382
            adress = y * 128 + x * 6;
383
            adress &= 0x3FF;
384
 
385
            for (i = 0; i < 6; i++)
386
            {
387
                    ch = pgm_read_byte (&font8x6[0][0] + i + c * 6);
388
 
389
                    switch (mode)
390
                    {
391
 
392
                    case 0:
393
                            display_buffer[adress+i] = ch;
394
                            break;
395
 
396
                    case 1:
397
                            display_buffer[adress+i] |= ch;
398
                            break;
399
 
400
                    case 2:
401
                            display_buffer[adress+i] ^= ch;
402
                            break;
403
 
404
                    case 3:
405
                            display_buffer[adress+i] &= ch;
406
                            break;
407
 
408
                    case 4:
409
                            display_buffer[adress+i] &= ~ch;
410
                            break;
411
                    }
412
 
413
                    set_adress (adress + i, display_buffer[adress + i]);
414
              }
415
       }
416
}
417
 
418
 
419
#if Jeti
420
//-----------------------------------------------------------
421
void lcd_putc_jeti (uint8_t x, uint8_t y, uint8_t c, uint8_t mode)
422
{
423
        uint8_t ch;
424
        uint8_t i;
425
        uint16_t adress;
426
        if (mode == 2)
427
                lcd_frect ((x*8),(y*8),8,8,1); // invertierte Darstellung
428
        switch (c)
429
        {
430
 
431
        case 0x7e:
432
                c = 0x1a; // ->
433
                break;
434
 
435
        case 0x7f:
436
                c = 0x1b; // <-
437
                break;
438
 
439
        case 0xdf:
440
                c = 0xf8; // °
441
                break;
442
        }
443
 
444
        adress = y * 128 + x * 8;
445
        adress &= 0x3FF;
446
 
447
        for (i = 0; i < 8; i++)
448
        {
449
                ch = pgm_read_byte (&Font8x8[0][0] + i + c * 8);
450
 
451
                switch (mode)
452
                {
453
 
454
                case 0:
455
                        display_buffer[adress+i] = ch;
456
                        break;
457
 
458
                case 1:
459
                        display_buffer[adress+i] |= ch;
460
                        break;
461
 
462
                case 2:
463
                        display_buffer[adress+i] ^= ch;
464
                        break;
465
 
466
                case 3:
467
                        display_buffer[adress+i] &= ch;
468
                        break;
469
 
470
                case 4:
471
                        display_buffer[adress+i] &= ~ch;
472
                        break;
473
                }
474
 
475
                set_adress (adress + i, display_buffer[adress + i]);
476
        }
477
}
478
 
479
 
480
//-----------------------------------------------------------
481
void lcd_printpj (const char *text, uint8_t mode)
482
{
483
        while (pgm_read_byte(text))
484
        {
485
                switch (pgm_read_byte(text))
486
                {
487
 
488
                case 0x0D:
489
                        lcd_xpos = 0;
490
                        break;
491
 
492
                case 0x0A:
493
                        new_line();
494
                        break;
495
 
496
                default:
497
                        lcd_putc_jeti (lcd_xpos, lcd_ypos, pgm_read_byte(text), mode);
498
                        lcd_xpos++;
499
                        if (lcd_xpos > 20)
500
                        {
501
                                lcd_xpos = 0;
502
                                new_line ();
503
                        }
504
                        break;
505
                }
506
                text++;
507
        }
508
}
509
 
510
 
511
//-----------------------------------------------------------
512
void lcd_printpj_at (uint8_t x, uint8_t y, const char *text, uint8_t mode)
513
{
514
        lcd_xpos = x;
515
        lcd_ypos = y;
516
        lcd_printpj (text, mode);
517
}
518
#endif
519
 
520
 
521
//-----------------------------------------------------------
522
void new_line (void)
523
{
524
        lcd_ypos++;
525
 
526
        if (lcd_ypos > 7)
527
        {
528
                scroll ();
529
                lcd_ypos = 7;
530
        }
531
}
532
 
533
 
534
//-----------------------------------------------------------
535
void lcd_printpns (const char *text, uint8_t mode)
536
{
537
        while (pgm_read_byte(text))
538
        {
539
                switch (pgm_read_byte(text))
540
                {
541
 
542
                case 0x0D:
543
                        lcd_xpos = 0;
544
                        break;
545
 
546
                case 0x0A:
547
                        new_line();
548
                        break;
549
 
550
                default:
551
                        lcd_putc (lcd_xpos, lcd_ypos, pgm_read_byte(text), mode);
552
                        lcd_xpos++;
553
                        if (lcd_xpos > 21)
554
                        {
555
                                lcd_xpos = 0;
556
//                              new_line ();
557
                        }
558
                        break;
559
                }
560
                text++;
561
        }
562
}
563
 
564
 
565
//-----------------------------------------------------------
566
void lcd_printpns_at (uint8_t x, uint8_t y, const char *text, uint8_t mode)
567
{
568
        lcd_xpos = x;
569
        lcd_ypos = y;
570
        lcd_printpns (text, mode);
571
}
572
 
573
 
574
//-----------------------------------------------------------
575
void lcd_printp (const char *text, uint8_t mode)
576
{
577
        while (pgm_read_byte(text))
578
        {
579
                switch (pgm_read_byte(text))
580
                {
581
 
582
                case 0x0D:
583
                        lcd_xpos = 0;
584
                        break;
585
 
586
                case 0x0A:
587
                        new_line();
588
                        break;
589
 
590
                default:
591
                        lcd_putc (lcd_xpos, lcd_ypos, pgm_read_byte(text), mode);
592
                        lcd_xpos++;
593
                        if (lcd_xpos > 21)
594
                        {
595
                                lcd_xpos = 0;
596
                                new_line ();
597
                        }
598
                        break;
599
                }
600
                text++;
601
        }
602
}
603
 
604
 
605
//-----------------------------------------------------------
606
void lcd_printp_at (uint8_t x, uint8_t y, const char *text, uint8_t mode)
607
{
608
        lcd_xpos = x;
609
        lcd_ypos = y;
610
        lcd_printp (text, mode);
611
}
612
 
613
 
614
//-----------------------------------------------------------
615
void lcd_print (uint8_t *text, uint8_t mode)
616
{
617
        while (*text)
618
        {
619
                switch (*text)
620
                {
621
 
622
                case 0x0D:
623
                        lcd_xpos = 0;
624
                        break;
625
 
626
                case 0x0A:
627
                        new_line();
628
                        break;
629
 
630
                default:
631
                        lcd_putc (lcd_xpos, lcd_ypos, *text, mode);
632
                        lcd_xpos++;
633
                        if (lcd_xpos > 21)
634
                        {
635
                                lcd_xpos = 0;
636
                                new_line ();
637
                        }
638
                        break;
639
                }
640
                text++;
641
        }
642
}
643
 
644
 
645
//-----------------------------------------------------------
646
void lcd_print_at (uint8_t x, uint8_t y, uint8_t *text, uint8_t mode)
647
{
648
        lcd_xpos = x;
649
        lcd_ypos = y;
650
        lcd_print (text, mode);
651
}
652
 
653
 
654
//-----------------------------------------------------------
655
void print_display (uint8_t *text)
656
{
657
        while (*text)
658
        {
659
                lcd_putc (lcd_xpos, lcd_ypos, *text, 0);
660
                lcd_xpos++;
661
                if (lcd_xpos >= 20)
662
                {
663
                        lcd_xpos = 0;
664
                        new_line ();
665
                }
666
                text++;
667
        }
668
}
669
 
670
 
671
//-----------------------------------------------------------
672
void print_display_at (uint8_t x, uint8_t y, uint8_t *text)
673
{
674
        lcd_xpos = x;
675
        lcd_ypos = y;
676
        print_display (text);
677
}
678
 
679
 
680
//-----------------------------------------------------------
681
// + Plot (set one Pixel)
682
//-----------------------------------------------------------
683
// mode:
684
// 0=Clear, 1=Set, 2=XOR
685
void lcd_plot (uint8_t xpos, uint8_t ypos, uint8_t mode)
686
{
687
        uint16_t adress;
688
        uint8_t mask;
689
 
690
        if ((xpos < DISP_W) && (ypos < DISP_H))
691
        {
692
                adress = (ypos / 8) * DISP_W + xpos;            // adress = 0/8 * 128 + 0   = 0
693
                mask = 1 << (ypos & 0x07);                                      // mask = 1<<0 = 1
694
                adress &= DISP_BUFFER - 1;
695
                switch (mode)
696
                {
697
 
698
                case 0:
699
                        display_buffer[adress] &= ~mask;
700
                        break;
701
 
702
                case 1:
703
                        display_buffer[adress] |= mask;
704
                        break;
705
 
706
                case 2:
707
                        display_buffer[adress] ^= mask;
708
                        break;
709
                }
710
                set_adress (adress, display_buffer[adress]);
711
        }
712
}
713
 
714
 
715
//-----------------------------------------------------------
716
// + Line (draws a line from x1,y1 to x2,y2
717
// + Based on Bresenham line-Algorithm
718
// + found in the internet, modified by thkais 2007
719
//-----------------------------------------------------------
720
 
721
void lcd_line (unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2, uint8_t mode)
722
{
723
        int x, y, count, xs, ys, xm, ym;
724
 
725
        x = (int) x1;
726
        y = (int) y1;
727
        xs = (int) x2 - (int) x1;
728
        ys = (int) y2 - (int) y1;
729
        if (xs < 0)
730
                xm = -1;
731
        else
732
                if (xs > 0)
733
                        xm = 1;
734
                else
735
                        xm = 0;
736
        if (ys < 0)
737
                ym = -1;
738
        else
739
                if (ys > 0)
740
                        ym = 1;
741
                else
742
                        ym = 0;
743
        if (xs < 0)
744
                xs = -xs;
745
 
746
        if (ys < 0)
747
                ys = -ys;
748
 
749
        lcd_plot ((unsigned char) x, (unsigned char) y, mode);
750
 
751
        if (xs > ys) // Flat Line <45 degrees
752
        {
753
                count = -(xs / 2);
754
                while (x != x2)
755
                {
756
                        count = count + ys;
757
                        x = x + xm;
758
                        if (count > 0)
759
                        {
760
                                y = y + ym;
761
                                count = count - xs;
762
                        }
763
                        lcd_plot ((unsigned char) x, (unsigned char) y, mode);
764
                }
765
        }
766
        else // Line >=45 degrees
767
        {
768
                count =- (ys / 2);
769
                while (y != y2)
770
                {
771
                        count = count + xs;
772
                        y = y + ym;
773
                        if (count > 0)
774
                        {
775
                                x = x + xm;
776
                                count = count - ys;
777
                        }
778
                        lcd_plot ((unsigned char) x, (unsigned char) y, mode);
779
                }
780
        }
781
}
782
 
783
 
784
//-----------------------------------------------------------
785
// + Filled rectangle
786
// + x1, y1 = upper left corner
787
//-----------------------------------------------------------
788
 
789
void lcd_frect (uint8_t x1, uint8_t y1, uint8_t widthx, uint8_t widthy, uint8_t mode)
790
{
791
        uint16_t x2, y2;
792
        uint16_t i;
793
 
794
        if (x1 >= DISP_W)
795
                x1 = DISP_W - 1;
796
 
797
        if (y1 >= DISP_H)
798
                y1 = DISP_H - 1;
799
 
800
        x2 = x1 + widthx;
801
        y2 = y1 + widthy;
802
 
803
        if (x2 > DISP_W)
804
                x2 = DISP_W;
805
 
806
        if (y2 > DISP_H)
807
                y2 = DISP_H;
808
 
809
        for (i = y1; i <= y2; i++)
810
        {
811
                lcd_line (x1, i, x2, i, mode);
812
        }
813
}
814
 
815
 
816
//-----------------------------------------------------------
817
// + outline of rectangle
818
// + x1, y1 = upper left corner
819
//-----------------------------------------------------------
820
 
821
void lcd_rect (uint8_t x1, uint8_t y1, uint8_t widthx, uint8_t widthy, uint8_t mode)
822
{
823
        uint16_t x2, y2;
824
 
825
        if (x1 >= DISP_W)
826
                x1 = DISP_W - 1;
827
        if (y1 >= DISP_H)
828
                y1 = DISP_H - 1;
829
        x2 = x1 + widthx;
830
        y2 = y1 + widthy;
831
 
832
        if (x2 > DISP_W)
833
                x2 = DISP_W;
834
 
835
        if (y2 > DISP_H)
836
                y2 = DISP_H;
837
 
838
        lcd_line (x1, y1, x2, y1, mode);
839
        lcd_line (x2, y1, x2, y2, mode);
840
        lcd_line (x2, y2, x1, y2, mode);
841
        lcd_line (x1, y2, x1, y1, mode);
842
}
843
 
844
 
845
//-----------------------------------------------------------
846
// + outline of a circle
847
// + Based on Bresenham-algorithm found in wikipedia
848
// + modified by thkais (2007)
849
//-----------------------------------------------------------
850
 
851
void lcd_circle (int16_t x0, int16_t y0, int16_t radius, uint8_t mode)
852
{
853
        int16_t f = 1 - radius;
854
        int16_t ddF_x = 0;
855
        int16_t ddF_y = -2 * radius;
856
        int16_t x = 0;
857
        int16_t y = radius;
858
 
859
        lcd_plot (x0, y0 + radius, mode);
860
        lcd_plot (x0, y0 - radius, mode);
861
        lcd_plot (x0 + radius, y0, mode);
862
        lcd_plot (x0 - radius, y0, mode);
863
 
864
        while (x < y)
865
        {
866
                if (f >= 0)
867
                {
868
                        y --;
869
                        ddF_y += 2;
870
                        f += ddF_y;
871
                }
872
                x ++;
873
                ddF_x += 2;
874
                f += ddF_x + 1;
875
 
876
                lcd_plot (x0 + x, y0 + y, mode);
877
                lcd_plot (x0 - x, y0 + y, mode);
878
 
879
                lcd_plot (x0 + x, y0 - y, mode);
880
                lcd_plot (x0 - x, y0 - y, mode);
881
 
882
                lcd_plot (x0 + y, y0 + x, mode);
883
                lcd_plot (x0 - y, y0 + x, mode);
884
 
885
                lcd_plot (x0 + y, y0 - x, mode);
886
                lcd_plot (x0 - y, y0 - x, mode);
887
        }
888
}
889
 
890
 
891
//-----------------------------------------------------------
892
// + filled Circle
893
// + modified circle-algorithm thkais (2007)
894
//-----------------------------------------------------------
895
 
896
void lcd_fcircle (int16_t x0, int16_t y0, int16_t radius,uint8_t mode)
897
{
898
        int16_t f = 1 - radius;
899
        int16_t ddF_x = 0;
900
        int16_t ddF_y = -2 * radius;
901
        int16_t x = 0;
902
        int16_t y = radius;
903
 
904
        lcd_line (x0, y0 + radius, x0, y0 - radius, mode);
905
 
906
        lcd_line (x0 + radius, y0, x0 - radius, y0, mode);
907
 
908
        while (x < y)
909
        {
910
                if (f >= 0)
911
                {
912
                        y--;
913
                        ddF_y += 2;
914
                        f += ddF_y;
915
                }
916
                x++;
917
                ddF_x += 2;
918
                f += ddF_x + 1;
919
 
920
                lcd_line (x0 + x, y0 + y, x0 - x, y0 + y, mode);
921
                lcd_line (x0 + x, y0 - y, x0 - x, y0 - y, mode);
922
                lcd_line (x0 + y, y0 + x, x0 - y, y0 + x, mode);
923
                lcd_line (x0 + y, y0 - x, x0 - y, y0 - x, mode);
924
        }
925
}
926
 
927
 
928
//-----------------------------------------------------------
929
//
930
void lcd_circ_line (uint8_t x, uint8_t y, uint8_t r, uint16_t deg, uint8_t mode)
931
{
932
        uint8_t xc, yc;
933
        double deg_rad;
934
 
935
        deg_rad = (deg * M_PI) / 180.0;
936
 
937
        yc = y - (uint8_t) round (cos (deg_rad) * (double) r);
938
        xc = x + (uint8_t) round (sin (deg_rad) * (double) r);
939
        lcd_line (x, y, xc, yc, mode);
940
}
941
 
942
 
943
//-----------------------------------------------------------
944
//
945
void lcd_ellipse_line (uint8_t x, uint8_t y, uint8_t rx, uint8_t ry, uint16_t deg, uint8_t mode)
946
{
947
        uint8_t xc, yc;
948
        double deg_rad;
949
 
950
        deg_rad = (deg * M_PI) / 180.0;
951
 
952
        yc = y - (uint8_t) round (cos (deg_rad) * (double) ry);
953
        xc = x + (uint8_t) round (sin (deg_rad) * (double) rx);
954
        lcd_line (x, y, xc, yc, mode);
955
}
956
 
957
 
958
//-----------------------------------------------------------
959
//
960
void lcd_ellipse (int16_t x0, int16_t y0, int16_t rx, int16_t ry, uint8_t mode)
961
{
962
        const int16_t rx2 = rx * rx;
963
        const int16_t ry2 = ry * ry;
964
        int16_t F = round (ry2 - rx2 * ry + 0.25 * rx2);
965
        int16_t ddF_x = 0;
966
        int16_t ddF_y = 2 * rx2 * ry;
967
        int16_t x = 0;
968
        int16_t y = ry;
969
 
970
        lcd_plot (x0, y0 + ry, mode);
971
        lcd_plot (x0, y0 - ry, mode);
972
        lcd_plot (x0 + rx, y0, mode);
973
        lcd_plot (x0 - rx, y0, mode);
974
        // while ( 2*ry2*x < 2*rx2*y ) {  we can use ddF_x and ddF_y
975
        while (ddF_x < ddF_y)
976
        {
977
                if(F >= 0)
978
                {
979
                        y     -= 1;             // south
980
                        ddF_y -= 2 * rx2;
981
                        F     -= ddF_y;
982
                }
983
                x     += 1;                     // east
984
                ddF_x += 2 * ry2;
985
                F     += ddF_x + ry2;
986
                lcd_plot (x0 + x, y0 + y, mode);
987
                lcd_plot (x0 + x, y0 - y, mode);
988
                lcd_plot (x0 - x, y0 + y, mode);
989
                lcd_plot (x0 - x, y0 - y, mode);
990
        }
991
        F = round (ry2 * (x + 0.5) * (x + 0.5) + rx2 * (y - 1) * (y - 1) - rx2 * ry2);
992
        while(y > 0)
993
        {
994
                if(F <= 0)
995
                {
996
                        x     += 1;             // east
997
                        ddF_x += 2 * ry2;
998
                        F     += ddF_x;
999
                }
1000
                y     -= 1;                     // south
1001
                ddF_y -= 2 * rx2;
1002
                F     += rx2 - ddF_y;
1003
                lcd_plot (x0 + x, y0 + y, mode);
1004
                lcd_plot (x0 + x, y0 - y, mode);
1005
                lcd_plot (x0 - x, y0 + y, mode);
1006
                lcd_plot (x0 - x, y0 - y, mode);
1007
        }
1008
}
1009
 
1010
 
1011
//-----------------------------------------------------------
1012
//
1013
void lcd_ecircle (int16_t x0, int16_t y0, int16_t radius, uint8_t mode)
1014
{
1015
        lcd_ellipse (x0, y0, radius + 3, radius, mode);
1016
}
1017
 
1018
 
1019
//-----------------------------------------------------------
1020
//
1021
void lcd_ecirc_line (uint8_t x, uint8_t y, uint8_t r, uint16_t deg, uint8_t mode)
1022
{
1023
        lcd_ellipse_line(x, y, r + 3, r, deg, mode);
1024
}
1025
 
1026
 
1027
//-----------------------------------------------------------
1028
//
1029
void lcd_view_font (uint8_t page)
1030
{
1031
        int x;
1032
        int y;
1033
 
1034
        lcd_cls ();
1035
        lcd_printp (PSTR("  0123456789ABCDEF\r\n"), 0);
1036
        lcd_printpns_at (0, 7, PSTR(" \x1a    \x1b     Exit"), 0);
1037
 
1038
        lcd_ypos = 2;
1039
        for (y = page * 4 ; y < (page * 4 + 4); y++)
1040
        {
1041
                if (y < 10)
1042
                {
1043
                        lcd_putc (0, lcd_ypos, '0' + y, 0);
1044
                }
1045
                else
1046
                {
1047
                        lcd_putc (0, lcd_ypos, 'A' + y - 10, 0);
1048
                }
1049
                lcd_xpos = 2;
1050
                for (x = 0; x < 16; x++)
1051
                {
1052
                        lcd_putc (lcd_xpos, lcd_ypos, y * 16 + x, 0);
1053
                        lcd_xpos++;
1054
                }
1055
                lcd_ypos++;
1056
        }
1057
}
1058
 
1059
 
1060
//-----------------------------------------------------------
1061
uint8_t hdigit (uint8_t d)
1062
{
1063
        if (d < 10)
1064
        {
1065
                return '0' + d;
1066
        }
1067
        else
1068
        {
1069
                return 'A' + d - 10;
1070
        }
1071
}
1072
 
1073
 
1074
//-----------------------------------------------------------
1075
void lcd_print_hex_at (uint8_t x, uint8_t y, uint8_t h, uint8_t mode)
1076
{
1077
        lcd_xpos = x;
1078
        lcd_ypos = y;
1079
 
1080
        lcd_putc (lcd_xpos++, lcd_ypos, hdigit (h >> 4), mode);
1081
        lcd_putc (lcd_xpos, lcd_ypos, hdigit (h & 0x0f), mode);
1082
}
1083
 
1084
 
1085
//-----------------------------------------------------------
1086
void lcd_print_hex (uint8_t h, uint8_t mode)
1087
{
1088
//      lcd_xpos = x;
1089
//      lcd_ypos = y;
1090
 
1091
        lcd_putc (lcd_xpos++, lcd_ypos, hdigit (h >> 4), mode);
1092
        lcd_putc (lcd_xpos++, lcd_ypos, hdigit (h & 0x0f), mode);
1093
        lcd_putc (lcd_xpos++, lcd_ypos, ' ', mode);
1094
}
1095
 
1096
 
1097
//-----------------------------------------------------------
1098
void lcd_write_number_u (uint8_t number)
1099
{
1100
        uint8_t num = 100;
1101
        uint8_t started = 0;
1102
 
1103
        while (num > 0)
1104
        {
1105
                uint8_t b = number / num;
1106
                if (b > 0 || started || num == 1)
1107
                {
1108
                        lcd_putc (lcd_xpos++, lcd_ypos, '0' + b, 0);
1109
                        started = 1;
1110
                }
1111
                number -= b * num;
1112
 
1113
                num /= 10;
1114
        }
1115
}
1116
 
1117
 
1118
//-----------------------------------------------------------
1119
void lcd_write_number_u_at (uint8_t x, uint8_t y, uint8_t number)
1120
{
1121
        lcd_xpos = x;
1122
        lcd_ypos = y;
1123
        lcd_write_number_u (number);
1124
}
1125
 
1126
 
1127
//-----------------------------------------------------------
1128
// Write only some digits of a unsigned <number> at <x>/<y> to MAX7456 display memory
1129
// <num> represents the largest multiple of 10 that will still be displayable as
1130
// the first digit, so num = 10 will be 0-99 and so on
1131
// <pad> = 1 will cause blank spaced to be filled up with zeros e.g. 007 instead of   7
1132
//
1133
void write_ndigit_number_u (uint8_t x, uint8_t y, uint16_t number, int16_t length, uint8_t pad, uint8_t mode)
1134
{
1135
        char s[7];
1136
 
1137
        utoa(number, s, 10 );
1138
 
1139
        uint8_t len = strlen(s);
1140
 
1141
        if (length < len)
1142
        {
1143
                for (uint8_t i = 0; i < length; i++)
1144
                {
1145
                        lcd_putc (x++, y, '*', mode);
1146
                }
1147
                return;
1148
        }
1149
 
1150
        for (uint8_t i = 0; i < length - len; i++)
1151
        {
1152
                if (pad==1)
1153
                {
1154
                        lcd_putc (x++, y, '0', mode);
1155
                }
1156
                else
1157
                {
1158
                        lcd_putc (x++, y, ' ', mode);
1159
                }
1160
        }
1161
        lcd_print_at(x, y, (uint8_t*)s, mode);
1162
}
1163
 
1164
//-----------------------------------------------------------
1165
// Write only some digits of a signed <number> at <x>/<y> to MAX7456 display memory
1166
// <num> represents the largest multiple of 10 that will still be displayable as
1167
// the first digit, so num = 10 will be 0-99 and so on
1168
// <pad> = 1 will cause blank spaced to be filled up with zeros e.g. 007 instead of   7
1169
//
1170
void write_ndigit_number_s (uint8_t x, uint8_t y, int16_t number, int16_t length, uint8_t pad, uint8_t mode)
1171
{
1172
        char s[7];
1173
 
1174
        itoa(number, s, 10 );
1175
 
1176
        uint8_t len = strlen(s);
1177
 
1178
        if (length < len)
1179
        {
1180
                for (uint8_t i = 0; i < length; i++)
1181
                {
1182
                        lcd_putc (x++, y, '*', mode);
1183
                }
1184
                return;
1185
        }
1186
 
1187
        for (uint8_t i = 0; i < length - len; i++)
1188
        {
1189
                if (pad)
1190
                {
1191
                        lcd_putc (x++, y, '0', mode);
1192
                }
1193
                else
1194
                {
1195
                        lcd_putc (x++, y, ' ', mode);
1196
                }
1197
        }
1198
        lcd_print_at(x, y, (uint8_t*)s, mode);
1199
}
1200
 
1201
 
1202
//-----------------------------------------------------------
1203
// Write only some digits of a unsigned <number> at <x>/<y> to MAX7456 display memory
1204
// as /10th of the value
1205
// <num> represents the largest multiple of 10 that will still be displayable as
1206
// the first digit, so num = 10 will be 0-99 and so on
1207
// <pad> = 1 will cause blank spaced to be filled up with zeros e.g. 007 instead of   7
1208
//
1209
void write_ndigit_number_u_10th (uint8_t x, uint8_t y, uint16_t number, int16_t length, uint8_t pad, uint8_t mode)
1210
{
1211
        char s[7];
1212
 
1213
        itoa(number, s, 10 );
1214
 
1215
        uint8_t len = strlen(s);
1216
 
1217
        if (length < len)
1218
        {
1219
                for (uint8_t i = 0; i < length; i++)
1220
                {
1221
                        lcd_putc (x++, y, '*', mode);
1222
                }
1223
                return;
1224
        }
1225
 
1226
        for (uint8_t i = 0; i < length - len; i++)
1227
        {
1228
                if (pad)
1229
                {
1230
                        lcd_putc (x++, y, '0', mode);
1231
                }
1232
                else
1233
                {
1234
                        lcd_putc (x++, y, ' ', mode);
1235
                }
1236
        }
1237
 
1238
        char rest = s[len - 1];
1239
 
1240
        s[len - 1] = 0;
1241
 
1242
        if (len == 1)
1243
        {
1244
                lcd_putc (x-1, y, '0', mode);
1245
        }
1246
        else if (len == 2 && s[0] == '-')
1247
        {
1248
                lcd_putc (x-1, y, '-', mode);
1249
                lcd_putc (x, y, '0', mode);
1250
        }
1251
        else
1252
        {
1253
                lcd_print_at(x, y, (uint8_t*)s, mode);
1254
        }
1255
        x += len - 1;
1256
        lcd_putc (x++, y, '.', mode);
1257
        lcd_putc (x++, y, rest, mode);
1258
}
1259
 
1260
 
1261
//-----------------------------------------------------------
1262
void write_ndigit_number_u_100th (uint8_t x, uint8_t y, uint16_t number, int16_t length, uint8_t pad)
1263
{
1264
        uint8_t num = 100;
1265
 
1266
        while (num > 0)
1267
        {
1268
                uint8_t b = number / num;
1269
 
1270
                if ((num / 10) == 1)
1271
                {
1272
                        lcd_putc (x++, y, '.', 0);
1273
                }
1274
                lcd_putc (x++, y, '0' + b, 0);
1275
                number -= b * num;
1276
 
1277
                num /= 10;
1278
        }
1279
}
1280
 
1281
 
1282
//-----------------------------------------------------------
1283
// Write only some digits of a signed <number> at <x>/<y> to MAX7456 display memory
1284
// as /10th of the value
1285
// <num> represents the largest multiple of 10 that will still be displayable as
1286
// the first digit, so num = 10 will be 0-99 and so on
1287
// <pad> = 1 will cause blank spaced to be filled up with zeros e.g. 007 instead of   7
1288
//
1289
void write_ndigit_number_s_10th (uint8_t x, uint8_t y, int16_t number, int16_t length, uint8_t pad, uint8_t mode)
1290
{
1291
        char s[7];
1292
 
1293
        itoa (number, s, 10 );
1294
 
1295
        uint8_t len = strlen(s);
1296
 
1297
        if (length < len)
1298
        {
1299
                for (uint8_t i = 0; i < length; i++)
1300
                {
1301
                        lcd_putc (x++, y, '*', mode);
1302
                }
1303
                return;
1304
        }
1305
 
1306
        for (uint8_t i = 0; i < length - len; i++)
1307
        {
1308
                if (pad)
1309
                {
1310
                        lcd_putc (x++, y, '0', mode);
1311
                }
1312
                else
1313
                {
1314
                        lcd_putc (x++, y, ' ', mode);
1315
                }
1316
        }
1317
 
1318
        char rest = s[len - 1];
1319
 
1320
        s[len - 1] = 0;
1321
 
1322
        if (len == 1)
1323
        {
1324
                lcd_putc (x-1, y, '0', mode);
1325
        }
1326
        else if (len == 2 && s[0] == '-')
1327
        {
1328
                lcd_putc (x-1, y, '-', mode);
1329
                lcd_putc (x, y, '0', mode);
1330
        }
1331
        else
1332
        {
1333
                lcd_print_at(x, y, (uint8_t*)s, mode);
1334
        }
1335
        x += len - 1;
1336
        lcd_putc (x++, y, '.', mode);
1337
        lcd_putc (x++, y, rest, mode);
1338
}
1339
 
1340
 
1341
//-----------------------------------------------------------
1342
// write <seconds> as human readable time at <x>/<y> to MAX7456 display mem
1343
//
1344
void write_time (uint8_t x, uint8_t y, uint16_t seconds)
1345
{
1346
        uint16_t min = seconds / 60;
1347
        seconds -= min * 60;
1348
        write_ndigit_number_u (x, y, min, 2, 0,0);
1349
        lcd_putc (x + 2, y, ':', 0);
1350
        write_ndigit_number_u (x + 3, y, seconds, 2, 1,0);
1351
}
1352
 
1353
 
1354
//-----------------------------------------------------------
1355
// wirte a <position> at <x>/<y> assuming it is a gps position for long-/latitude
1356
//
1357
void write_gps_pos (uint8_t x, uint8_t y, int32_t position)
1358
{
1359
        if (position < 0)
1360
        {
1361
                position ^= ~0;
1362
                position++;
1363
                lcd_putc (x++, y, '-', 0);
1364
        }
1365
        else
1366
        {
1367
                lcd_putc (x++, y, ' ', 0);
1368
        }
1369
        write_ndigit_number_u (x, y, (uint16_t) (position / (int32_t) 10000000), 3, 1,0);
1370
        lcd_putc (x + 3, y, '.', 0);
1371
        position = position - ((position / (int32_t) 10000000) * (int32_t) 10000000);
1372
        write_ndigit_number_u (x + 4, y, (uint16_t) (position / (int32_t) 1000), 4, 1,0);
1373
        position = position - ((uint16_t) (position / (int32_t) 1000) * (int32_t) 1000);
1374
        write_ndigit_number_u (x + 8, y, (uint16_t) position, 3, 1,0);
1375
        lcd_putc (x + 11, y, 0x1e, 0);  // degree symbol
1376
}
1377
 
1378