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