-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsource.c
323 lines (315 loc) · 7.4 KB
/
source.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
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
/*
* THIS IS A SIMPLE SYSTEM DESIGNED TO PROVIDE TIME AND DATE FOR END USERS
* IT HAS THE CAPABILITY TO PROVIDE DATE IN FORME : dayName XX/XX/20XX, ALSO THE TIME IS IN FORME OF : XX/XX/XX
* ALSO THE SYSTEM SUPPORTS DUAL LANGUAGES(ENGLISH AND FRENSH).
* THE HOURSE ARE DISPLAYED AS (24)
* HOW TO WORKS *
* WE ARE USING SPI PROTOCOL TO COMMUNICATE WITH THE RTC MAX6902 WHICH IS A SIMPLE DEVICE THAT PROVIDES ACCURATE TIME AND DATA
* USING INTERRUPT TO HANLD PRECISELY EACH DEVIC(EXTERNAL INTERRUPT FROM INT0, INT1, SPI).
* WE ARE USING FINIT STATE MACHINE TO HANDL THE READ/WRITE OPERATIONS TO/FROM THE MAX6902(NOT SWITCH, IF-ELSE)
* THE DATE AND TIME ARE DISPLAYED INTO LCD, ONCE THE INT0 IS TRIGGERED, THE SYSTEM DISPLAYS TWO LANGUAGES(ENGLISH AND FRENSH)
* AFTER CHOOSING THE LANGUAGE VIA THE INT0(YOU NEED TO CLICK INT0 TO CHANGE THE ARROW POSITION) THE INT1 IS USED TO VALIDE THE LANGUAGE CHOOSEN.
*/
#include <p18f452.h>
#include "definitions.h"
#pragma config WDT = OFF
#pragma interrupt interruptFunction
void interruptFunction(void)
{
if(INTCONbits.INT0IF)
{
INTCONbits.INT0IF = 0;
if(!choose)
{
PIE1bits.SSPIE = 0; // DISABLE SPI INTERRUPT
SLAVE_SELECT = 1; // DISABLE COMMUNICATION WITH SLAVE
INTCON3bits.INT1IE = 1; // ENABLE INT0 INTERRUPT
INTCON3bits.INT1IF = 0;
choose = 0x01; // STATE CHANGES
clearHome(); // CLEAR LCD ENTIRELY
displayParameter(); // DISPLAY THE PARAMETERS INTO LCD
}
else
{
changePosition = ~changePosition; // EACH TIME INT0 IS TRIGGERED BY A BUTTON PUSH THE changePosition VALUE IS COMPLEMENTED
changeArrowPosition(); // BASED ON THE changePosition VALUE, THE ARROW IS EITHER POINTING TO FIRST CHOICE OR SECOND CHOICE
}
}
else if(INTCON3bits.INT1IF) // THIS BLOCK IS USED TO VALIDATE USE CHOICE
{
INTCON3bits.INT1IF = 0;
INTCON3bits.INT1IE = 0; // DISABLE THE INT1 (THIS IS ACTIVATED ONLY WHEN THE INT0 IS TRIGERREED)
PIE1bits.SSPIE = 1; // ACTIVATE SPI INTERRUPT
clearHome(); // CLEAR HOME
choose = 0; // RESET THE CHOOSE VARIABLE
SLAVE_SELECT = 0; // PULL THE SLAVE SELECT PIN LOW
SSPBUF = CLOCK_BURST_READ; // INITIATE COMMUNICATION WITH SLAVE THROUGH BURST MODE
}
else if(PIE1bits.SSPIE) // THIS BLOCK IS FOR SPI ISR CODE
{
if(PIR1bits.SSPIF)
{
PIR1bits.SSPIF = 0;
if(spiState == WRITE)
{
if(i < 8)
SSPBUF = bytes[i++];
else
{
SLAVE_SELECT = 1;
spiState = READ;
reg = DUMMY;
SLAVE_SELECT = 0;
i = 0;
SSPBUF = CLOCK_BURST_READ;
}
}
else
{
if(reg == DUMMY) // SEND DUMMY DATA
{
SSPBUF = DUMMY_DATA;
reg = SAVE;
}
else // STORE THE RECEIVED DATA FROM MISO LINE
{
reg = DUMMY;
bytes[i++] = SSPBUF;
if(i < 8)
PIR1bits.SSPIF = 1; // TRIGGER A SOFTWARE SPI INTERRUPT
else
{
reg = DUMMY;
SLAVE_SELECT = 1; // DISCONNECTED THE SLAVE
displayResult(); // DISPLAY DATA INTO LCD
SLAVE_SELECT = 0;
SSPBUF = CLOCK_BURST_READ; // INITIATE A BURST MODE READING
i = 0;
}
}
}
}
}
}
#pragma code vector = 0x00008
void vector(void)
{
_asm
GOTO interruptFunction
_endasm
}
#pragma code
void main(void)
{
TRISD = 0x00; // ALL PINS ARE OUTPUT
TRISC = 0x90; // MAKE SERIAL PINS AS OUTPUT + LCD CONTROL PINS OUTPUT
SSPSTAT = 0xC0; // CONFIGURATION OF SPI PROTOCOL
SSPCON1 = 0x20;
initialization(); // INITIALIZATION OF LCD(CLEAR HOME, CURSOR OFF, 5*7 PIXEL SIZE)
INTCONbits.GIE = 1; // GLOBAL INTERRUPT ENABLE
INTCONbits.PEIE = 1; // PERIPHERAL INTERRUPT ENABLE
INTCONbits.INT0IE = 1;
INTCONbits.INT0IF = 0;
PIE1bits.SSPIE = 1; // SPI INTERRUPT BIT
PIR1bits.SSPIF = 0; // INTERRUPT FLAG
SLAVE_SELECT = 0;
SSPBUF = CLOCK_BURST_WRITE; // INITIATE BURST MODE WRITE TO SLAVE
while(TRUE); // KEEP LOOPING
}
void changeArrowPosition(void) // THE FUNCTION ROLE'S TO HANLD ARROW POSITION
{
if(changePosition)
{
home(ARROW_SECOND_LINE);
displaySpace(); // CLEAR PREVIOUS ARROW FROM THE SECOND LINE
home(ARROW_THIRD_LINE);
displayArrow(); // DISPLAY ARROW
}
else
{
home(ARROW_THIRD_LINE);
displaySpace(); // CLEAR PREVIOUS ARROW FROM THE THIRD LINE
home(ARROW_SECOND_LINE);
displayArrow();
}
}
void displaySpace(void)
{
LATD = 0x20; // 0x20 IS THE ASCII CODE OF A SPACE
data();
}
void displayArrow(void)
{
LATD = '>'; // ARROW CHARATCER
data();
}
void displayParameter(void) // THE FUNCTION ROLE'S TO DISPLAY ALL THE SUPPORTED LANGUAGES BY THE SYSTEM
{
unsigned char strings[3][16] = {" LANGUAGE :", " ENGLISH", " FRENSH"}, i = 0;
while(i < 3)
{
displayString(strings[i]);
if(i == 0)
home(0xC0);
else if(i == 1)
home(0x94);
++i;
}
home(0xC4);
displayArrow();
}
void clearHome(void)
{
LATD = 0x01;
command();
T0CON = 0x80;
TMR0H = 0xF9;
TMR0L = 0x8E;
timerZero();
}
void home(unsigned char value) // THIS FUNCTION IS USED TO CHANGE THE POSITION OF THE CURSOR(SECOND LINE, FIRST LINE)
{
LATD = value;
command();
busyFlag();
}
void displayTime(void) // THIS IS USED FOR DISPLAYING TIME
{
signed char m = 2;
home(0xC6);
while(m >= 0)
{
LATD = 0x30 + ((bytes[m] & 0xF0) >> 4); // EXTRACT THE HIGH BYTE TO DISPLAY IT
data();
LATD = 0x30 + (bytes[m] & 0x0F); // EXTRACT THE LOW BYTE TO DISPLAY IT
data();
if(m != 0) // DISPLAY TIME IN THIS FORMAT : x:x:x
{
LATD = ':';
data();
}
--m;
}
}
void displayString(const unsigned char* string)
{
unsigned char i = 0;
for(; string[i] != '\0'; ++i)
{
LATD = string[i];
data();
}
}
void displayDate(void) // THIS FUNCTION DISPLAYS DATE : x/x/20x
{
unsigned char m = (bytes[5] - 1), n = 0, date = bytes[3], month = bytes[4], year = bytes[6];
home(0x94);
if(m > 7)
m = 0;
if(!changePosition)
displayString(daysInEnglish[m]);
else
displayString(daysInFrensh[m]);
LATD = 0x30 + ((date & 0xF0) >> 4);
data();
LATD = 0x30 + (date & 0x0F);
data();
LATD = '/';
data();
LATD = 0x30 + ((month & 0xF0) >> 4);
data();
LATD = 0x30 + (month & 0x0F);
data();
LATD = '/';
data();
LATD = 0x32;
data();
LATD = 0x30;
data();
LATD = 0x30 + ((year & 0xF0) >> 4);
data();
LATD = 0x30 + (year & 0x0F);
data();
displaySpace();
displaySpace();
displaySpace();
}
void displayInformation(void) // THIS FUNCTION DISPLAYS INFORMATIONS
{
unsigned char inforEnglish[] = "DATE & TIME", i = 0, inforFrensh[] = "TEMPS & DATE";
home(0x84);
if(!changePosition)
displayString(inforEnglish);
else
displayString(inforFrensh);
}
void displayResult(void)
{
displayInformation();
displayTime();
displayDate();
}
void initialization(void)
{
LATD = 0x38;
command();
delay250ms();
LATD = 0x01;
command();
delay250ms();
LATD = 0x0C;
command();
delay250ms();
}
void delay250ms(void)
{
T0CON = 0x01;
TMR0H = 0x0B;
TMR0L = 0xBC;
timerZero();
}
void delay3us(void)
{
T0CON = 0x48;
TMR0L = 253;
timerZero();
}
void command(void)
{
RS_PIN = 0;
RW_PIN = 0;
EN_PIN = 1;
delay3us();
EN_PIN = 0;
}
void data(void)
{
RS_PIN = 1;
RW_PIN = 0;
EN_PIN = 1;
delay3us();
EN_PIN = 0;
busyFlag();
}
void busyFlag(void)
{
RS_PIN = 0;
RW_PIN = 1;
TRISDbits.TRISD7 = 1;
do
{
EN_PIN = 1;
delay3us();
EN_PIN = 0;
}while(PORTDbits.RD7 == 1);
EN_PIN = 0;
TRISDbits.TRISD7 = 0;
}
void timerZero(void)
{
INTCONbits.TMR0IF = 0;
T0CONbits.TMR0ON = 1;
while(INTCONbits.TMR0IF == 0);
INTCONbits.TMR0IF = 0;
T0CONbits.TMR0ON = 0;
}