LCDControllerDEM120064A.asm


1
; Display Test for LCD DEM120064
2
; (C) Mario Latzig 2017
3
;
4
; on ATtiny2313(A), 4 MHz ext. Crystal
5
;
6
; PB0: CS      (Chip Select, active Low)
7
; PB1: RES     (Reset, active Low)
8
; PB2: DC      (Data=High / Command=Low)
9
; PB3: SCK     (Serial Clock, Data is triggered on Low-High-Edge)
10
; PB4: SDA     (Serial Data) 
11
;
12
; PD2: LED     (Test LED, active High)          
13
14
; *****************************************************************************
15
; *** Definitions                                                           ***
16
; *****************************************************************************
17
.def temp = r0                ; Temporary Register (Memory load)
18
.def zero = r1                ; (always Zero)
19
.def stat = r2                ; Temporary Status Register
20
.def a = r16                ; Temporary Register (a)  
21
.def b = r17                ; Temporary Register (b)
22
.def c = r18                ; Temporary Register (c)
23
.def d = r19                ; Temporary Register (d)
24
.def e = r20                ; Temporary Register (e)
25
.def f = r21                ; Temporary Register (f)
26
.def g = r22                ; Temporary Register (g)
27
.def pdat = r23                ; Temporary Port Register
28
.def ol = r24                ; Counter Register (LO)
29
.def oh = r25                ; Counter Register (HI)
30
31
; --- General -----------------------------------------------------------------
32
.equ FC = 4000000              ; Clock = 4 MHz (ext. Crystal)
33
34
; --- Pins --------------------------------------------------------------------
35
.equ PINB_CS = (1<<0)            ; PB0: CS      (Chip Select, active Low)
36
.equ PINB_RES = (1<<1)            ; PB1: RES     (Reset, active Low)
37
.equ PINB_DC = (1<<2)            ; PB2: DC      (Data=High / Command=Low)
38
.equ PINB_SCK = (1<<3)            ; PB3: SCK     (Serial Clock, Data is triggered on Low-High-Edge)
39
.equ PINB_SDA = (1<<4)            ; PB4: SDA     (Serial Data) 
40
41
.equ PIND_LED = (1<<2)            ; PD2: LED     (Test LED, active High)  
42
43
; === LCD =====================================================================
44
; $00: Set Lower Column Address
45
.equ LCD_SET_COL_LO = 0x00
46
; $10: Set Higher Column Address
47
.equ LCD_SET_COL_HI = 0x10
48
; $20: Set Internal Regulator Resistor Ratio (X0-X2: Internal regulator gain increases as X2X1X0 increased from 000b to 111b. At POR = 100b)
49
.equ LCD_SET_INT_REG_RES_RATIO = 0x20
50
; $28: Set Power Control Register (X0: Output op-amp buffer, X1: internal regulator,X2: internal voltage booster)
51
.equ LCD_SET_POWER_CTRL = 0x28
52
; $81: Set Contrast 
53
.equ LCD_SET_CONTRAST = 0x81
54
; $A0: Set Segment Re-map (X0=0: Col Addr $00=SEG0 (POR), X0=1: Col Addr $83=SEG0)
55
.equ LCD_CMD_SEGMENT_REMAP = 0xA0      
56
; $A2: Set LCD Bias (X0=0: 1/9 Bias, X0=1: 1/7 Bias)
57
.equ LCD_CMD_BIAS = 0xA2          
58
; $A6: Set Normal/Reverse Display (X0=0: normal display (POR), X0=1: reverse display)
59
.equ LCD_SET_NORMAL_DISPLAY = 0xA6          
60
; $A9: Set Bias Ratio / Set TC Value / Modify Osc. Freq.
61
.equ LCD_SET_BIAS_TC_OSC = 0xA9
62
; $AE: Set Entire Display On/Off (X0=0: normal display (POR), X0=1: entire display on)
63
.equ LCD_SET_DISPLAY = 0xAE
64
; $B0: Set Set Page Address
65
.equ LCD_SET_PAGE = 0xB0
66
; $C0: Set COM Output Scan Direction (X3=0: COM0 to COM[N-1] (POR), X3=1:  COM[N-1] to COM0)
67
.equ LCD_SET_COM_OUTPUT_SCAN_DIR = 0xC0
68
69
.equ LCD_COLS = 20              ; Number of Chars per Row
70
.equ LCD_ROWS = 8              ; Number of Rows
71
72
; *****************************************************************************
73
; *** SRAM                                                                  ***
74
; *****************************************************************************
75
.dseg 
76
77
; *****************************************************************************
78
; *** Vectors                                                               ***
79
; *****************************************************************************
80
.cseg
81
.org 0x0000
82
    rjmp init
83
.org INT_VECTORS_SIZE
84
85
; *****************************************************************************
86
; *** Main                                                                  ***
87
; *****************************************************************************
88
.include "font.inc"
89
90
; ### INIT ####################################################################
91
92
init:
93
    cli                  ; Disable interrupts
94
95
    clr zero              ; Reset Zero Register
96
    ldi a,LOW(RAMEND)          ; Init Stack Pointer
97
    out SPL,a
98
    
99
    rcall led_init            ; Inits Test LED
100
    rcall lcd_init            ; Inits LCD
101
102
    sei                  ; Enable interrupts
103
104
; ### TEST ####################################################################
105
106
test:
107
    ldi a,'!'
108
    ldi oh,0
109
test_loop_row:
110
    ldi ol,0
111
test_loop_col:
112
    rcall lcd_char
113
    inc a
114
    cpi a,0x7F
115
    brne test_loop_cnt
116
    ldi a,'!'|0x80
117
test_loop_cnt:
118
    inc ol
119
    cpi ol,LCD_COLS
120
    brlo test_loop_col
121
    inc oh
122
    cpi oh,LCD_ROWS
123
    brlo test_loop_row
124
125
test_hold:
126
    rjmp test_hold
127
128
; *****************************************************************************
129
; *** LCD                                                                   ***
130
; *****************************************************************************
131
132
; ### Inits LCD
133
lcd_init:
134
    push a
135
    push b
136
    push pdat
137
138
    in pdat,PORTB
139
    sbr pdat,PINB_RES|PINB_CS
140
    cbr pdat,PINB_SCK|PINB_SDA|PINB_DC
141
    out PORTB,pdat
142
    in a,DDRB
143
    sbr a,PINB_SCK|PINB_SDA|PINB_DC|PINB_CS|PINB_RES
144
    out DDRB,a
145
146
    ser a                ; Enable Test LED
147
    rcall led_set
148
149
    cbr pdat,PINB_RES          ; Trigger HW Reset of LCD
150
    out PORTB,pdat
151
    rcall util_delay_10us
152
    sbr pdat,PINB_RES
153
    out PORTB,pdat
154
155
    ldi a,LCD_CMD_BIAS|0        ; Init Sequence
156
    rcall lcd_cmd
157
    ldi a,LCD_CMD_SEGMENT_REMAP|0
158
    rcall lcd_cmd
159
    ldi a,LCD_SET_COM_OUTPUT_SCAN_DIR|8
160
    rcall lcd_cmd
161
    ldi a,LCD_SET_INT_REG_RES_RATIO|5
162
    rcall lcd_cmd
163
    ldi a,LCD_SET_NORMAL_DISPLAY
164
    rcall lcd_cmd
165
    ldi a,LCD_SET_POWER_CTRL|7
166
    rcall lcd_cmd
167
    ldi a,LCD_SET_DISPLAY|1
168
    rcall lcd_cmd
169
    ldi a,LCD_SET_CONTRAST
170
    ldi b,0x20
171
    rcall lcd_cmd2
172
173
    clr a                ; Disable Test LED
174
    rcall led_set
175
176
    pop pdat
177
    pop b
178
    pop a
179
    ret
180
181
; ### Draw Char
182
; >a: The ASCII Char (0-127), Bit7: Invert Flag
183
; >ol: The Column (0-19)
184
; >oh: The Row (0-7)
185
lcd_char:
186
    push temp
187
    push a
188
    push b
189
    push pdat
190
    push ol
191
    push oh
192
    push zl
193
    push zh
194
  
195
lcd_char_chk:    
196
    mov temp,a
197
    cpi ol,LCD_COLS            ; ### Check Range
198
    brsh lcd_char_exit
199
    cpi oh,LCD_ROWS
200
    brsh lcd_char_exit
201
202
lcd_char_col:                ; ### Set LCD Column 
203
    lsl ol
204
    mov b,ol              ; (Multiply Char Column by 6)
205
    lsl ol
206
    add b,ol
207
    subi b,-6
208
    mov a,b
209
    andi a,0x0F
210
    ori a,LCD_SET_COL_LO
211
    rcall lcd_cmd
212
    mov a,b
213
    swap a
214
    andi a,0x0F
215
    ori a,LCD_SET_COL_HI
216
    rcall lcd_cmd
217
lcd_char_row:                ; ### Set LCD Page Address 
218
    mov a,oh              ; (Using Char Row)
219
    ori a,LCD_SET_PAGE
220
    rcall lcd_cmd
221
222
lcd_char_font:                ; ### Calculate Font Address 
223
    ldi zl,LOW(2*FONT5X7)        ; Offset = (ASCII Char - 0x20) * 5
224
    ldi zh,HIGH(2*FONT5X7)
225
    mov a,temp
226
    andi a,0x7F
227
    cpi a,' '
228
    brsh lcd_char_font_cnt
229
    ldi a,' '
230
lcd_char_font_cnt:  
231
    subi a,' '      
232
    clr b
233
    add zl,a
234
    adc zh,b
235
    lsl a
236
    rol b
237
    lsl a
238
    rol b
239
    add zl,a
240
    adc zh,b
241
242
lcd_char_draw:                ; ### Draw Char 
243
    in pdat,PORTB            ; Enable Chip Select
244
    cbr pdat,PINB_CS
245
    out PORTB,pdat
246
247
    ldi ol,5              ; Set 5 Bytes as Data
248
lcd_char_draw_loop:
249
    lpm a,z+
250
    sbrc temp,7
251
    com a
252
    ser b
253
    rcall lcd_byte
254
    dec ol
255
    brne lcd_char_draw_loop
256
    clr a                ; Add 1 Byte as Space
257
    sbrc temp,7
258
    com a
259
    rcall lcd_byte
260
261
    in pdat,PORTB            ; Disable Chip Select
262
    sbr pdat,PINB_CS
263
    out PORTB,pdat
264
265
lcd_char_exit:
266
    pop zh
267
    pop zl
268
    pop oh
269
    pop ol
270
    pop pdat
271
    pop b
272
    pop a
273
    pop temp
274
    ret
275
276
; ### Send 2-Byte Command
277
; >a: The Command
278
; >b: The Data
279
lcd_cmd2:
280
    push temp
281
    push a
282
    push b
283
    push pdat
284
285
    in pdat,PORTB            ; Enable Chip Select
286
    cbr pdat,PINB_CS
287
    out PORTB,pdat
288
289
    mov temp,b              ; Send Command
290
    clr b                
291
    rcall lcd_byte
292
    mov a,temp              ; Send Data
293
    rcall lcd_byte
294
295
    in pdat,PORTB            ; Disable Chip Select
296
    sbr pdat,PINB_CS
297
    out PORTB,pdat
298
299
    pop pdat
300
    pop b
301
    pop a
302
    pop temp
303
    ret
304
305
; ### Send Single Command Byte
306
; >a: The Command
307
lcd_cmd:
308
    push b
309
    push pdat
310
311
    in pdat,PORTB            ; Enable Chip Select
312
    cbr pdat,PINB_CS
313
    out PORTB,pdat
314
315
    clr b                ; Send Byte
316
    rcall lcd_byte
317
318
    in pdat,PORTB            ; Disable Chip Select
319
    sbr pdat,PINB_CS
320
    out PORTB,pdat
321
322
    pop pdat
323
    pop b
324
    ret
325
326
; ### Shift Byte
327
; >a: The Byte
328
; >b: The DC Flag
329
lcd_byte:
330
    push a
331
    push b
332
    push pdat
333
334
    in pdat,PORTB            ; Set DC Pin
335
    cbr pdat,PINB_DC
336
    cpse b,zero
337
    sbr pdat,PINB_DC
338
    out PORTB,pdat    
339
340
lcd_byte_shift:                ; Bit-Banging Input Byte (MSB first)
341
    ldi b,8                  
342
lcd_byte_shift_loop:
343
    cbr pdat,PINB_SDA
344
    lsl a
345
    brcc lcd_byte_shift_cnt
346
    sbr pdat,PINB_SDA
347
lcd_byte_shift_cnt:
348
    out PORTB,pdat    
349
    sbr pdat,PINB_SCK
350
    out PORTB,pdat    
351
    cbr pdat,PINB_SCK
352
    out PORTB,pdat    
353
    dec b
354
    brne lcd_byte_shift_loop
355
356
    pop pdat
357
    pop b
358
    pop a
359
    ret
360
361
; *****************************************************************************
362
; *** Test LED                                                              ***
363
; *****************************************************************************
364
365
; ### Inits LED
366
led_init:
367
    push a
368
    
369
    in a,DDRD              ; Set LED Pins to Output
370
    sbr a,PIND_LED
371
    out DDRD,a
372
    
373
    ser a                ; Flash LED
374
    rcall led_set            
375
    ldi a,250
376
    rcall util_delay_Xms
377
    clr a
378
    rcall led_set            
379
    ldi a,250
380
    rcall util_delay_Xms
381
382
    pop a
383
    ret
384
385
386
; ### Switch LED
387
; >a: The enabled flag
388
led_set:
389
    push pdat
390
391
    in pdat,PORTD
392
    cbr pdat,PIND_LED
393
    cpse a,zero
394
    sbr pdat,PIND_LED
395
    out PORTD,pdat
396
397
    pop pdat
398
    ret
399
400
; *****************************************************************************
401
; *** Core Utility                                                          ***
402
; *****************************************************************************
403
404
; ### Delay 10us
405
.equ CLK10US = ((FC/100000)-12)/3      ; Constant for 10us including RCALL
406
util_delay_10us:
407
    push a                ; 1 x push = 2 clocks
408
409
    ldi a,CLK10US            ; 1 x load = 1 clock
410
util_delay_10us_loop:            
411
    dec a                ; N * 3 clocks
412
    brne util_delay_10us_loop
413
414
    pop a                ; 1 x pop + ret = 6 clocks
415
    ret
416
417
; ### Delay 1ms
418
.equ CLK1MS = ((FC/1000)-17)/4        ; Constant for 1ms including RCALL
419
util_delay_1ms: 
420
    push ol                ; 2 x push = 4 clocks
421
    push oh                
422
423
    ldi oh,HIGH(CLK1MS)          ; 2 x load = 2 clocks
424
    ldi ol,LOW(CLK1MS)
425
util_delay_1ms_loop:
426
    sbiw ol,1              ; N * 4 clocks
427
    brne util_delay_1ms_loop 
428
429
    pop oh                ; 2 x pop + ret = 8 clocks 
430
    pop ol
431
    ret
432
433
; ### Delay X*0-255 ms
434
; (tolerance by additional 2+X*(0+1+2)+2+4
435
; >a: value of ms
436
util_delay_Xms:
437
    push a
438
439
util_delay_Xms_loop:            ; Delays X times for one millisecond
440
    rcall util_delay_1ms        ; Cycles for RCALL are already included in calculation here
441
    dec a
442
    brne util_delay_Xms_loop
443
444
    pop a
445
    ret