forked from ImperialCollegeLondon/MicroprocessorsLab
-
Notifications
You must be signed in to change notification settings - Fork 0
/
LCD.asm
140 lines (123 loc) · 3.83 KB
/
LCD.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include p18f87k22.inc
; code to operate the LCD
global LCD_Setup, LCD_Write_Message, LCD_Send_Byte_I, LCD_delay_x4us, LCD_Send_Byte_D
acs0 udata_acs ; named variables in access ram
LCD_cnt_l res 1 ; reserve 1 byte for variable LCD_cnt_l
LCD_cnt_h res 1 ; reserve 1 byte for variable LCD_cnt_h
LCD_cnt_ms res 1 ; reserve 1 byte for ms counter
LCD_tmp res 1 ; reserve 1 byte for temporary use
LCD_counter res 1 ; reserve 1 byte for counting through nessage
constant LCD_E=5 ; LCD enable bit
constant LCD_RS=4 ; LCD register select bit
LCD code 0x400
LCD_Setup
clrf LATB
movlw b'11000000' ; RB0:5 all outputs
movwf TRISB
movlw .40
call LCD_delay_ms ; wait 40ms for LCD to start up properly
movlw b'00110000' ; Function set 4-bit
call LCD_Send_Byte_I
movlw .10 ; wait 40us
call LCD_delay_x4us
movlw b'00101000' ; 2 line display 5x8 dot characters
call LCD_Send_Byte_I
movlw .10 ; wait 40us
call LCD_delay_x4us
movlw b'00101000' ; repeat, 2 line display 5x8 dot characters
call LCD_Send_Byte_I
movlw .10 ; wait 40us
call LCD_delay_x4us
movlw b'00001111' ; display on, cursor on, blinking on
call LCD_Send_Byte_I
movlw .10 ; wait 40us
call LCD_delay_x4us
movlw b'00000001' ; display clear
call LCD_Send_Byte_I
movlw .2 ; wait 2ms
call LCD_delay_ms
movlw b'00000110' ; entry mode incr by 1 no shift
call LCD_Send_Byte_I
movlw .10 ; wait 40us
call LCD_delay_x4us
return
LCD_Write_Message ; Message stored at FSR2, length stored in W
movwf LCD_counter
LCD_Loop_message
movf POSTINC2, W
call LCD_Send_Byte_D
decfsz LCD_counter
bra LCD_Loop_message
return
LCD_Send_Byte_I ; Transmits byte stored in W to instruction reg
movwf LCD_tmp
swapf LCD_tmp,W ; swap nibbles, high nibble goes first
andlw 0x0f ; select just low nibble
movwf LATB ; output data bits to LCD
bcf LATB, LCD_RS ; Instruction write clear RS bit
call LCD_Enable ; Pulse enable Bit
movf LCD_tmp,W ; swap nibbles, now do low nibble
andlw 0x0f ; select just low nibble
movwf LATB ; output data bits to LCD
bcf LATB, LCD_RS ; Instruction write clear RS bit
call LCD_Enable ; Pulse enable Bit
return
LCD_Send_Byte_D ; Transmits byte stored in W to data reg
movwf LCD_tmp
swapf LCD_tmp,W ; swap nibbles, high nibble goes first
andlw 0x0f ; select just low nibble
movwf LATB ; output data bits to LCD
bsf LATB, LCD_RS ; Data write set RS bit
call LCD_Enable ; Pulse enable Bit
movf LCD_tmp,W ; swap nibbles, now do low nibble
andlw 0x0f ; select just low nibble
movwf LATB ; output data bits to LCD
bsf LATB, LCD_RS ; Data write set RS bit
call LCD_Enable ; Pulse enable Bit
movlw .10 ; delay 40us
call LCD_delay_x4us
return
LCD_Enable ; pulse enable bit LCD_E for 500ns
nop
nop
nop
nop
nop
nop
nop
nop
bsf LATB, LCD_E ; Take enable high
nop
nop
nop
nop
nop
nop
nop
bcf LATB, LCD_E ; Writes data to LCD
return
; ** a few delay routines below here as LCD timing can be quite critical ****
LCD_delay_ms ; delay given in ms in W
movwf LCD_cnt_ms
lcdlp2 movlw .250 ; 1 ms delay
call LCD_delay_x4us
decfsz LCD_cnt_ms
bra lcdlp2
return
LCD_delay_x4us ; delay given in chunks of 4 microsecond in W
movwf LCD_cnt_l ; now need to multiply by 16
swapf LCD_cnt_l,F ; swap nibbles
movlw 0x0f
andwf LCD_cnt_l,W ; move low nibble to W
movwf LCD_cnt_h ; then to LCD_cnt_h
movlw 0xf0
andwf LCD_cnt_l,F ; keep high nibble in LCD_cnt_l
call LCD_delay
return
LCD_delay ; delay routine 4 instruction loop == 250ns
movlw 0x00 ; W=0
lcdlp1 decf LCD_cnt_l,F ; no carry when 0x00 -> 0xff
subwfb LCD_cnt_h,F ; no carry when 0x00 -> 0xff
bc lcdlp1 ; carry, then loop again
return ; carry reset so return
end