ST7920.c


1
//-------------------------------------------------------------------------------------------------
2
//
3
//-------------------------------------------------------------------------------------------------
4
#include <avr/io.h>
5
6
//#define INTERFACE_8_BIT
7
8
// save program memory -> we do not use _delay_us()
9
// 1 nop per MHz (adapt if needed)
10
#define DELAY_1US \
11
    {           \
12
    __asm__ __volatile__("nop"); \
13
    __asm__ __volatile__("nop"); \
14
    __asm__ __volatile__("nop"); \
15
    __asm__ __volatile__("nop"); \
16
    __asm__ __volatile__("nop"); \
17
    __asm__ __volatile__("nop"); \
18
    __asm__ __volatile__("nop"); \
19
    __asm__ __volatile__("nop"); \
20
    __asm__ __volatile__("nop"); \
21
    __asm__ __volatile__("nop"); \
22
    __asm__ __volatile__("nop"); \
23
    __asm__ __volatile__("nop"); \
24
    }
25
26
27
28
#define CMD_DISPLAY_CLEAR   0x01
29
#define CMD_RETURN_HOME     0x02
30
#define CMD_ENTRY_MODE      0x04
31
#define CMD_DISPLAY_CONTROL 0x08
32
#define CMD_CURSOR_CONTROL  0x10
33
#define CMD_FUNCTION_SET    0x20
34
#define CMD_SET_CGRAM_ADR   0x40
35
#define CMD_SET_DDRAM_ADR   0x80
36
37
#define CMDE_STANDBY        0x01
38
#define CMDE_SCROLL_SEL     0x02
39
#define CMDE_REVERSE_LINE   0x04
40
#define CMDE_SET_SCROLL_ADR 0x40
41
#define CMDE_SET_GDRAM_ADR  0x80
42
43
#define BIT_ID              0x02
44
#define BIT_S               0x01
45
#define BIT_D               0x04
46
#define BIT_C               0x02
47
#define BIT_B               0x01
48
#define BIT_SC              0x08
49
#define BIT_SR              0x01
50
#define BIT_RL              0x04
51
#define BIT_DL              0x10
52
#define BIT_RE              0x04
53
#define BIT_G               0x02
54
#define BIT_BUSY            0x80
55
56
#define MASK_CGRAM_ADR      0x3F
57
#define MASK_DDRAM_ADR      0x3F
58
#define MASK_SCROLL_ADR     0x3F
59
#define MASK_GDRAM_ADR_HOR  0x0F
60
#define MASK_GDRAM_ADR_VER  0x3F
61
62
#define PORT_BL     PORTA
63
#define DDR_BL      DDRA
64
#define BIT_BL      PA0
65
//#define BL_PIN_USED
66
67
#ifdef INTERFACE_8_BIT
68
#define PORT_D0     PORTD
69
#define PIN_D0      PIND
70
#define DDR_D0      DDRD
71
#define BIT_D0      PC1
72
73
#define PORT_D1     PORTD
74
#define PIN_D1      PIND
75
#define DDR_D1      DDRD
76
#define BIT_D1      PD3
77
78
#define PORT_D2     PORTD
79
#define PIN_D2      PIND
80
#define DDR_D2      DDRD
81
#define BIT_D2      PD0
82
83
#define PORT_D3     PORTD
84
#define PIN_D3      PIND
85
#define DDR_D3      DDRD
86
#define BIT_D3      PD4
87
#endif
88
89
#define PORT_D4     PORTC
90
#define PIN_D4      PINC
91
#define DDR_D4      DDRC
92
#define BIT_D4      PC0
93
94
#define PORT_D5     PORTC
95
#define PIN_D5      PINC
96
#define DDR_D5      DDRC
97
#define BIT_D5      PC1
98
99
#define PORT_D6     PORTC
100
#define PIN_D6      PINC
101
#define DDR_D6      DDRC
102
#define BIT_D6      PC2
103
104
#define PORT_D7     PORTC
105
#define PIN_D7      PINC
106
#define DDR_D7      DDRC
107
#define BIT_D7      PC3
108
109
#define PORT_E      PORTB
110
#define DDR_E       DDRB
111
#define BIT_E       PB2
112
113
#define PORT_RW     PORTB
114
#define DDR_RW      DDRB
115
#define BIT_RW      PB3
116
117
#define PORT_RS     PORTB
118
#define DDR_RS      DDRB
119
#define BIT_RS      PB1
120
121
#define PORT_RES    PORTB
122
#define DDR_RES     DDRB
123
#define BIT_RES     PB1
124
//#define RESET_PIN_USED
125
126
#define RS_DATA     1
127
#define RS_CMD      0
128
129
130
static uint8_t G_ExtendedMode = 0;
131
132
static void RS (uint8_t val)
133
{
134
    if (val)
135
        PORT_RS |= (1<<BIT_RS);
136
    else
137
        PORT_RS &= ~(1<<BIT_RS);
138
}
139
140
static void E (uint8_t val)
141
{
142
    if (val)
143
        PORT_E  |= (1<<BIT_E);
144
    else
145
        PORT_E &= ~(1<<BIT_E);
146
}
147
148
static void RW (uint8_t val)
149
{
150
    if (val)
151
        PORT_RW |= (1<<BIT_RW);
152
    else
153
        PORT_RW &= ~(1<<BIT_RW);
154
}
155
156
#ifdef RESET_PIN_USED
157
static void RES (uint8_t val)
158
{
159
    if (val)
160
        PORT_RES |= (1<<BIT_RES);
161
    else
162
        PORT_RES &= ~(1<<BIT_RES);
163
}
164
#endif
165
166
#ifdef BL_PIN_USED
167
static void Backlight (uint8_t val)
168
{
169
    if (val)
170
        PORT_BL |= (1<<BIT_BL);
171
    else
172
        PORT_BL &= ~(1<<BIT_BL);
173
}
174
#endif
175
176
__attribute__ ((noinline)) void Delay (uint32_t dval)
177
{
178
    while (dval--)
179
        DELAY_1US;
180
}
181
182
//-------------------------------------------------------------------------------------------------
183
//
184
//-------------------------------------------------------------------------------------------------
185
186
static void GLCD_InitPorts(void)
187
{
188
    RS(0);
189
    RW(1);
190
    E(0);
191
#ifdef RESET_PIN_USED
192
    RES(1);
193
    DDR_RES |= (1<<BIT_RES);
194
#endif
195
196
    DDR_E   |= (1<<BIT_E);
197
    DDR_RW  |= (1<<BIT_RW);
198
    DDR_RS  |= (1<<BIT_RS);
199
200
#ifdef INTERFACE_8_BIT
201
    DDR_D0  &= ~(1<<BIT_D0);
202
    DDR_D1  &= ~(1<<BIT_D1);
203
    DDR_D2  &= ~(1<<BIT_D2);
204
    DDR_D3  &= ~(1<<BIT_D3);
205
#endif
206
    DDR_D4  &= ~(1<<BIT_D4);
207
    DDR_D5  &= ~(1<<BIT_D5);
208
    DDR_D6  &= ~(1<<BIT_D6);
209
    DDR_D7  &= ~(1<<BIT_D7);
210
}
211
212
static void SetDataOutput (void)
213
{
214
    #ifdef INTERFACE_8_BIT
215
    DDR_D0  |= (1<<BIT_D0);
216
    DDR_D1  |= (1<<BIT_D1);
217
    DDR_D2  |= (1<<BIT_D2);
218
    DDR_D3  |= (1<<BIT_D3);
219
    #endif
220
    DDR_D4  |= (1<<BIT_D4);
221
    DDR_D5  |= (1<<BIT_D5);
222
    DDR_D6  |= (1<<BIT_D6);
223
    DDR_D7  |= (1<<BIT_D7);
224
}
225
226
static void SetDataInput (void)
227
{
228
#ifdef INTERFACE_8_BIT
229
    DDR_D0  &= ~(1<<BIT_D0);
230
    DDR_D1  &= ~(1<<BIT_D1);
231
    DDR_D2  &= ~(1<<BIT_D2);
232
    DDR_D3  &= ~(1<<BIT_D3);
233
#endif
234
    DDR_D4  &= ~(1<<BIT_D4);
235
    DDR_D5  &= ~(1<<BIT_D5);
236
    DDR_D6  &= ~(1<<BIT_D6);
237
    DDR_D7  &= ~(1<<BIT_D7);
238
}
239
240
static void DataOut (uint8_t data)
241
{
242
#ifdef INTERFACE_8_BIT
243
    if (data&0x01) PORT_D0 |= (1<<BIT_D0); else PORT_D0 &= ~(1<<BIT_D0);
244
    if (data&0x02) PORT_D1 |= (1<<BIT_D1); else PORT_D1 &= ~(1<<BIT_D1);
245
    if (data&0x04) PORT_D2 |= (1<<BIT_D2); else PORT_D2 &= ~(1<<BIT_D2);
246
    if (data&0x08) PORT_D3 |= (1<<BIT_D3); else PORT_D3 &= ~(1<<BIT_D3);
247
    if (data&0x10) PORT_D4 |= (1<<BIT_D4); else PORT_D4 &= ~(1<<BIT_D4);
248
    if (data&0x20) PORT_D5 |= (1<<BIT_D5); else PORT_D5 &= ~(1<<BIT_D5);
249
    if (data&0x40) PORT_D6 |= (1<<BIT_D6); else PORT_D6 &= ~(1<<BIT_D6);
250
    if (data&0x80) PORT_D7 |= (1<<BIT_D7); else PORT_D7 &= ~(1<<BIT_D7);
251
#else
252
    if (data&0x01) PORT_D4 |= (1<<BIT_D4); else PORT_D4 &= ~(1<<BIT_D4);
253
    if (data&0x02) PORT_D5 |= (1<<BIT_D5); else PORT_D5 &= ~(1<<BIT_D5);
254
    if (data&0x04) PORT_D6 |= (1<<BIT_D6); else PORT_D6 &= ~(1<<BIT_D6);
255
    if (data&0x08) PORT_D7 |= (1<<BIT_D7); else PORT_D7 &= ~(1<<BIT_D7);
256
#endif
257
    SetDataOutput();
258
}
259
260
261
static uint8_t DataIn (void)
262
{
263
    uint8_t data=0;
264
265
#ifdef INTERFACE_8_BIT
266
    PORT_D0 &= ~(1<<BIT_D0);
267
    PORT_D1 &= ~(1<<BIT_D1);
268
    PORT_D2 &= ~(1<<BIT_D2);
269
    PORT_D3 &= ~(1<<BIT_D3);
270
#endif
271
    PORT_D4 &= ~(1<<BIT_D4);
272
    PORT_D5 &= ~(1<<BIT_D5);
273
    PORT_D6 &= ~(1<<BIT_D6);
274
    PORT_D7 &= ~(1<<BIT_D7);
275
276
    SetDataInput();
277
278
    data = (data<<1) | ((PIN_D7>>BIT_D7)&1);
279
    data = (data<<1) | ((PIN_D6>>BIT_D6)&1);
280
    data = (data<<1) | ((PIN_D5>>BIT_D5)&1);
281
    data = (data<<1) | ((PIN_D4>>BIT_D4)&1);
282
#ifdef INTERFACE_8_BIT
283
    data = (data<<1) | ((PIN_D3>>BIT_D3)&1);
284
    data = (data<<1) | ((PIN_D2>>BIT_D2)&1);
285
    data = (data<<1) | ((PIN_D1>>BIT_D1)&1);
286
    data = (data<<1) | ((PIN_D0>>BIT_D0)&1);
287
#endif
288
289
    return(data);
290
}
291
292
293
//-------------------------------------------------------------------------------------------------
294
// Read
295
//-------------------------------------------------------------------------------------------------
296
static uint8_t GLCD_rawRead(uint8_t regsel)
297
{
298
    uint8_t tmp;
299
300
    E(0);
301
    SetDataInput();
302
    RS(regsel);
303
    RW(1);
304
    Delay(1);
305
    E(1);
306
    Delay(1);
307
    tmp = DataIn();
308
    E(0);
309
    Delay(1);
310
#ifndef INTERFACE_8_BIT
311
    E(1);
312
    Delay(1);
313
    tmp <<= 4;
314
    tmp |= DataIn();
315
    E(0);
316
    Delay(1);
317
#endif
318
319
    return tmp;
320
}
321
322
//-------------------------------------------------------------------------------------------------
323
// Wait Busy
324
//-------------------------------------------------------------------------------------------------
325
static void GLCD_WaitBusy(void)
326
{
327
    while(GLCD_rawRead(0)&BIT_BUSY);
328
}
329
330
//-------------------------------------------------------------------------------------------------
331
// Read
332
//-------------------------------------------------------------------------------------------------
333
static uint8_t GLCD_Read(uint8_t regsel)
334
{
335
    uint8_t tmp;
336
337
    E(0);
338
    SetDataInput();
339
    RS(regsel);
340
    RW(1);
341
    Delay(1);
342
    E(1);
343
    Delay(1);
344
    tmp = DataIn();
345
    E(0);
346
    Delay(1);
347
#ifndef INTERFACE_8_BIT
348
    E(1);
349
    Delay(1);
350
    tmp <<= 4;
351
    tmp |= DataIn();
352
    E(0);
353
    Delay(1);
354
#endif
355
    GLCD_WaitBusy();
356
357
    return tmp;
358
}
359
360
//-------------------------------------------------------------------------------------------------
361
// Write
362
//-------------------------------------------------------------------------------------------------
363
static void GLCD_Write(uint8_t regsel, uint8_t val)
364
{
365
    SetDataOutput();
366
    RS(regsel);
367
    RW(0);
368
#ifdef INTERFACE_8_BIT
369
    DataOut(val);
370
    Delay(1);
371
    E(1);
372
    Delay(1);
373
    E(0);
374
#else
375
    DataOut(val>>4);
376
    Delay(1);
377
    E(1);
378
    Delay(1);
379
    E(0);
380
    DataOut(val&0xF);
381
    Delay(1);
382
    E(1);
383
    Delay(1);
384
    E(0);
385
#endif
386
    RW(1);
387
    RS(1);
388
    SetDataInput();
389
390
    GLCD_WaitBusy();
391
392
}
393
//-------------------------------------------------------------------------------------------------
394
// BasicMode
395
//-------------------------------------------------------------------------------------------------
396
static void GLCD_SetBasicMode(void)
397
{
398
    if (G_ExtendedMode)
399
    {
400
#ifdef INTERFACE_8_BIT
401
        GLCD_Write(RS_CMD,CMD_FUNCTION_SET|BIT_DL);
402
#else
403
        GLCD_Write(RS_CMD,CMD_FUNCTION_SET);
404
#endif
405
        G_ExtendedMode = 0;
406
    }
407
}
408
409
//-------------------------------------------------------------------------------------------------
410
// ExtendedMode
411
//-------------------------------------------------------------------------------------------------
412
static void GLCD_SetExtendedMode(void)
413
{
414
    if (!G_ExtendedMode)
415
    {
416
#ifdef INTERFACE_8_BIT
417
        GLCD_Write(RS_CMD,CMD_FUNCTION_SET|BIT_DL|BIT_RE|BIT_G);
418
#else
419
        GLCD_Write(RS_CMD,CMD_FUNCTION_SET|BIT_RE|BIT_G);
420
#endif
421
        G_ExtendedMode = 1;
422
    }
423
}
424
425
//-------------------------------------------------------------------------------------------------
426
// ClearTXT
427
//-------------------------------------------------------------------------------------------------
428
void GLCD_ClearTXT(void)
429
{
430
    GLCD_SetBasicMode();
431
    GLCD_Write(RS_CMD,CMD_DISPLAY_CLEAR);
432
    GLCD_WaitBusy();
433
}
434
435
//-------------------------------------------------------------------------------------------------
436
// ClearGFX
437
//-------------------------------------------------------------------------------------------------
438
void GLCD_ClearGFX(void)
439
{
440
    uint8_t x,y;
441
442
    GLCD_SetExtendedMode();
443
    GLCD_Write(RS_CMD,CMDE_SET_GDRAM_ADR);
444
    GLCD_Write(RS_CMD,CMDE_SET_GDRAM_ADR);
445
446
    for (y=0;y<64;y++)
447
    {
448
        GLCD_Write(RS_CMD,CMDE_SET_GDRAM_ADR|(MASK_GDRAM_ADR_VER&y));
449
        GLCD_Write(RS_CMD,CMDE_SET_GDRAM_ADR);
450
        for (x=0;x<32;x++)
451
            GLCD_Write(RS_DATA,0x0);
452
    }
453
}
454
455
//-------------------------------------------------------------------------------------------------
456
// SetPixel
457
//-------------------------------------------------------------------------------------------------
458
void GLCD_SetPixel(uint8_t x,uint8_t y, uint8_t color)
459
{
460
    uint8_t subpos;
461
    uint8_t pix;
462
    uint8_t pixel_low;
463
    uint8_t pixel_high;
464
465
    GLCD_SetExtendedMode();
466
    GLCD_Write(RS_CMD,CMDE_SET_GDRAM_ADR|(MASK_GDRAM_ADR_VER&y));
467
    GLCD_Write(RS_CMD,CMDE_SET_GDRAM_ADR|(MASK_GDRAM_ADR_HOR&(x>>4)));
468
    GLCD_Read(RS_DATA);
469
    pixel_high  = GLCD_Read(RS_DATA);
470
    pixel_low   = GLCD_Read(RS_DATA);
471
472
    subpos = x & 0x0F;
473
    GLCD_Write(RS_CMD,CMDE_SET_GDRAM_ADR|(MASK_GDRAM_ADR_VER&y));
474
    GLCD_Write(RS_CMD,CMDE_SET_GDRAM_ADR|(MASK_GDRAM_ADR_HOR&(x>>4)));
475
476
    if (subpos < 8)
477
    {
478
        pix = color ? (1<<(7-subpos))|pixel_high : (~(1<<(7-subpos)))&pixel_high;
479
        GLCD_Write(RS_DATA,pix);
480
        GLCD_Write(RS_DATA,pixel_low);
481
    }
482
    else
483
    {
484
        pix = color ? (1<<(15-subpos))|pixel_low : (~(1<<(7-subpos)))&pixel_low;
485
        GLCD_Write(RS_DATA,pixel_high);
486
        GLCD_Write(RS_DATA,pix);
487
    }
488
}
489
490
//-------------------------------------------------------------------------------------------------
491
// Vertical Offset
492
//-------------------------------------------------------------------------------------------------
493
void GLCD_VerticalOffset(uint8_t offs)
494
{
495
    GLCD_SetExtendedMode();
496
497
498
    GLCD_Write(RS_CMD,CMDE_SCROLL_SEL|BIT_SR);
499
    GLCD_Write(RS_CMD,CMDE_SET_SCROLL_ADR|(MASK_SCROLL_ADR&offs));
500
    GLCD_Write(RS_CMD,CMDE_SCROLL_SEL);
501
    GLCD_WaitBusy();
502
}
503
504
505
506
//-------------------------------------------------------------------------------------------------
507
//
508
//-------------------------------------------------------------------------------------------------
509
void GLCD_WriteString(uint8_t x, uint8_t y,char * s)
510
{
511
    GLCD_SetBasicMode();
512
    GLCD_Write(RS_CMD,CMD_SET_DDRAM_ADR|(y*16+(x&0x1E)));
513
    if (x&1)
514
        GLCD_Write(RS_DATA,' ');
515
    while(*s)
516
    {
517
        GLCD_Write(RS_DATA,*s);
518
        s++;
519
    }
520
}
521
522
523
524
//-------------------------------------------------------------------------------------------------
525
//
526
//-------------------------------------------------------------------------------------------------
527
void GLCD_Init(void)
528
{
529
    GLCD_InitPorts();
530
531
#ifdef RESET_PIN_USED
532
    RES(0);
533
    Delay(10000);
534
    RES(1);
535
#endif
536
537
    Delay(100000);
538
539
#ifdef INTERFACE_8_BIT
540
    GLCD_Write(RS_CMD,CMD_FUNCTION_SET|BIT_DL);
541
    GLCD_Write(RS_CMD,CMD_FUNCTION_SET|BIT_DL);
542
#else
543
    GLCD_Write(RS_CMD,CMD_FUNCTION_SET);
544
    GLCD_Write(RS_CMD,CMD_FUNCTION_SET);
545
#endif
546
    GLCD_Write(RS_CMD,CMD_DISPLAY_CONTROL|BIT_D);
547
    Delay(100);
548
    GLCD_Write(RS_CMD,CMD_DISPLAY_CLEAR);
549
    Delay(100);
550
    GLCD_Write(RS_CMD,CMD_ENTRY_MODE|BIT_ID);
551
    Delay(100);
552
    G_ExtendedMode = 0;
553
}