-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlcd.c
298 lines (243 loc) · 7.12 KB
/
lcd.c
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
#include <msp430g2553.h>
#include <intrinsics.h>
#include "chars2.h"
/*****************************************************************************
To communicate with LCD we need 8 data pins and 4 command pins out of 16 av.
DB0 - DB7 : p1.0 - p1.7 // data pins
RS : p2.0 // L - reset / H - working
R/W : p2.1 // H - read / L - write
CS1 : p2.2 // Select column 1 ~ 64
CS2 : p2.3 // Select column 65 ~ 128
D/I : p2.4 // H - data / L - instruction
E : p2.5 // H - enable signal
shiftReg : p2.6 / #19
shiftRegClock : p2.7 / #18
GPIO registers contents:
P1OUT = [ [DB7] [DB6] [DB5] [DB4] [DB3] [DB2] [DB1] [DB0] ]
P2OUT = [ [ - ] [ - ] [E ] [D/I] [CS2] [CS1] [R/W] [RS ] ]
******************************************************************************
Display size:
2 displays, each one has
X: vertical pages: 8 pages, 8 pixels each
Y: horizontal lines, 64 lines
******************************************************************************/
// P2OUT WRITE BITS
#define LCD_RS BIT0;
#define LCD_RW BIT1;
#define LCD_CS1 BIT2;
#define LCD_CS2 BIT3;
#define LCD_DI BIT4;
#define LCD_E BIT5;
// DELAYS in Nano Seconds
#define LCD_tAS 186 /* Address setup time (ctrl line changes to E HIGH */
#define LCD_tDDR 248 /* Data setup time (data lines setup to dropping E) */
#define LCD_tDH 186 /* common data hold delay after E drop down */
// DIRECTIONS
#define LCD_DATA_INPUT 0x00
#define LCD_DATA_OUTPUT 0xff
// DEBUG BLINING
#define LCD_GRN_BLINK 0x40 // LED1 is red
#define LCD_RED_BLINK 0x01 // LED2 is green
#define LCD_BOTH_BLINK 0x41 // use both
// STATUS READ BITS
#define LCD_BUSY BIT7
#define LCD_ONOFF BIT5
#define LCD_RESET BIT4
// COMMANDS
#define CMD_SETX 0xB8
#define CMD_SETY 0x40
#define CMD_SETZ 0xC0
#define CMD_ON 0x3F
#define CMD_OFF 0x3E
#define F_CPU 16000000 // one cycle is 62 ns
#define lcdDelay1Ms() __delay_cycles(16130) // 1ms delay
#define lcdDelayNs(__ns) __delay_cycles( (double)__ns / 62 ) // one cycle is 62ns @ 16MHz
#define setPinLow(__pin) P2OUT &= ~__pin
#define setPinHigh(__pin) P2OUT |= __pin
/* LCD usage */
#define LCD_USE_1 0x00
#define LCD_USE_2 0x01
#define LCD_USE_BOTH 0x02
/* data input */
#define SHIFT_REG_CLOCK_MAX 10 // 0x0A
#define TARGET_CPU 0x00
#define TARGET_FREE 0x01
#define TARGET_UPTIME 0x02
#define TARGEt_NET_IN 0x03
#define TARGET_NET_OUT 0x04
#define TARGETS_COUNT 0x05
#define CMD_MASK 0x7F
#define CMD_LENGTH_BITS 0x07
#define CMD_CLEAR 0x7F /* clear command is 127 / 01111111 */
//const int char_map[] = { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 14, 26, 43, 45, 0, 0 };
volatile int shiftReg = 0x00; // new bits are received into here and put from the right
volatile int shiftRegClock = 0; // counter - as soon as it gets to 8, the shift register is treated as a command value
volatile int targetIndex[5] = {2,2,2,2,2};
/* first two letters in the target lines are always first lettter of the target name and semicolon */
volatile int targets[5][16] = {
{ 35, 26, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0 },
{ 38, 26, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0 },
{ 53, 26, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0 },
{ 41, 26, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0 },
{ 47, 26, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0 }
};
void lcdDelayMs(int ms) {
int i;
for (i=0; i < ms; i++)
lcdDelay1Ms();
}
void enable() { // pulse E signal
lcdDelayNs(LCD_tDH);
setPinHigh(LCD_E);
lcdDelayNs(LCD_tDDR);
setPinLow(LCD_E);
lcdDelayNs(LCD_tDH);
}
void useDisplay(int dn) {
switch(dn) {
case LCD_USE_1: setPinLow(LCD_CS1); setPinHigh(LCD_CS2); break;
case LCD_USE_2: setPinLow(LCD_CS2); setPinHigh(LCD_CS1); break;
default: setPinLow(LCD_CS1); setPinLow(LCD_CS2);
}
}
void waitReady() {
P1OUT = 0x00;
P1DIR = LCD_DATA_INPUT;
setPinLow(LCD_DI);
setPinHigh(LCD_RW);
lcdDelayNs(LCD_tAS);
setPinHigh(LCD_E);
lcdDelayNs(LCD_tDDR);
while (P1IN & LCD_BUSY) { // while display is busy
;
}
setPinLow(LCD_E);
lcdDelayNs(LCD_tDH);
P1DIR |= 0xff;
P1OUT = 0x00;
}
void writeCommand(char cmd) {
waitReady();
P1OUT = cmd;
setPinLow(LCD_DI);
setPinLow(LCD_RW);
enable();
}
void goToXY(int x, int y) {
if (x < 0 || x > 63 || y < 0 || y > 63) return;
// x : 0 - 7 pages /8
// y : 0 - 63 lines
int page = x / 8;
writeCommand(CMD_SETX | page);
writeCommand(CMD_SETY | y);
}
void writeData(char data) {
waitReady();
setPinHigh(LCD_DI);
setPinLow(LCD_RW);
P1OUT = data;
enable();
}
void clearScreen(int full) {
int i,j;
if (full == 0x01) {
useDisplay(LCD_USE_BOTH);
}
writeCommand(CMD_SETZ | 0x00);
writeCommand(CMD_SETX | 0x00);
writeCommand(CMD_SETY | 0x00);
for (i=0; i<8; i++) {
writeCommand(CMD_SETX | i);
writeCommand(CMD_SETY | 0);
for (j=0; j<64; j++) {
writeData(0x00);
}
}
}
void printChar(int cNumber) {
// find char in charSet var and print it from charMap
if (cNumber < 0 || cNumber >= charIndexMax) return;
int j;
for (j=0; j<8; j++) {
writeData(charMap[cNumber][j]);
}
}
void redraw() {
int i;
int j;
for (i = 0; i < TARGETS_COUNT; i++) {
useDisplay(LCD_USE_1);
writeCommand(CMD_SETX | i);
writeCommand(CMD_SETY);
for (j=0; j<8; j++) {
printChar(targets[i][j]);
}
useDisplay(LCD_USE_2);
writeCommand(CMD_SETX | i);
writeCommand(CMD_SETY);
for (j=8; j<16; j++) {
printChar(targets[i][j]);
}
}
}
int main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
BCSCTL3 |= LFXT1S_2; // Enable basic clock system control
IFG1 &= ~OFIFG; // clear interrupt register in case clock triggered it
BCSCTL1 = CALBC1_16MHZ; // calibrate clocks to run @ 16 MHz
DCOCTL = CALDCO_16MHZ; // calibrate clocks to run @ 16 MHz
P2SEL &= ~BIT6;
P2SEL &= ~BIT7;
P1DIR |= 0xff; // everyone is output
P2DIR = 0x3F; // P2.0 - P2.5 are output
P1OUT = 0x00;
P2OUT &= 0xC0; // reset only first six pains (output) to zero
P2IE |= BIT7 ; // Interrupt on Input Pin P2.6 & P2.7
_BIS_SR(GIE);
lcdDelayMs(20);
useDisplay(LCD_USE_BOTH);
clearScreen(0x02);
writeCommand(CMD_SETX | 0);
writeCommand(CMD_SETY | 0);
writeCommand(CMD_SETZ | 0);
writeCommand(CMD_ON);
lcdDelayMs(50);
shiftReg = 0;
shiftRegClock = 0;
while(1) {
lcdDelayMs(1000);
redraw();
}
return 0;
}
#pragma vector = PORT2_VECTOR
__interrupt void InterruptVectorPort2() {
if (P2IFG & BIT7) { /* if it was pin#7 who interrupted */
P2IFG &= ~BIT7; /* Clear Interrupt Flag */
shiftReg = shiftReg << 1;
if (P2IN & BIT6) { // check the state of pin#6
shiftReg |= BIT0;
} else {
shiftReg &= ~BIT0;
}
shiftRegClock++;
if (shiftRegClock >= SHIFT_REG_CLOCK_MAX) { /* size of shift reg clock is reached */
int command = shiftReg & CMD_MASK;
int target = shiftReg >> CMD_LENGTH_BITS;
if (command == CMD_CLEAR) { /* clear str command */
int c = 0;
for (c = 2; c < 16; c++)
targets[target][c] = 0;
targetIndex[target]=2;
} else {
targets[target][targetIndex[target]] = command;
if (targetIndex[target] >= 15)
targetIndex[target] = 2;
else
targetIndex[target]++;
}
shiftReg = 0;
shiftRegClock = 0;
}
}
}