-
Notifications
You must be signed in to change notification settings - Fork 0
/
Speedometer.c
154 lines (125 loc) · 3.31 KB
/
Speedometer.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
/*
* Speeedometer
* Author: Jeff Hansen
* Description:
Simulate a speedometer (kilometers per hour),
1 second is 1 minute (didn't want to wait 1 real minute to see changes..)
Have fun.
* License: MIT - do what you want, but I did the original work - don't forget.
*/
#include <utils.h>
// Address in the EEPROM where the first of the 2 bytes of data reside.
#define KM_ADDR 0x10
// LCD module connections
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;
sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// End LCD module connections
// Globals
unsigned int adcInput;
unsigned int timerCounter;
bit shouldUpdateSpeedometer;
bit shouldUpdateTotal;
/*
* Umion for managing ints in EEPROM
*/
union eeprom_int {
unsigned int value;
char memory[2];
};
/*
* Called by hardware Interrupt when the interrupt was generated by a timer.
*/
void timerInterrupt() {
if(timerCounter % 50 == 0) {
// Half a seccond has ellapsed
shouldUpdateSpeedometer = 1;
}
if(timerCounter % 100 == 0) {
// One second has ellapsed
shouldUpdateTotal = 1;
// Reset the timer counter - not required but why not.
timerCounter = 0;
}
timerCounter++;
}
/*
* Hardware interrupt.
*/
void interrupt(){
if (TMR0IF_bit){
TMR0IF_bit = 0;
TMR0 = 100;
timerInterrupt();
}
}
/*
Initializes all globals and sets default bits in registers.
*/
void initialize(){
C1ON_bit = 0; // Disable comparators
C2ON_bit = 0;
ANSEL = 0x04; // Configure AN2 pin as analog
ANSELH = 0; // Configure other AN pins as digital I/O
// Initialize timer 0 to interrupt every 10ms
OPTION_REG = 0x86;
TMR0 = 100;
INTCON = 0xA0;
// Init LCD
Lcd_Init();
Lcd_Cmd(_LCD_CLEAR);
// Initialize globals
timerCounter = 0;
}
/*
* Entry point
*/
void main() {
// Variables
char speedBuf[5] = {0,0,0,0,0};
char totalBuf[] = {0,0,0,0,0,0,0,0,0,0};
char empty[] = " ";
union eeprom_int totalKm;
int kph = 1;
// Initialization
initialize();
// 0x10 = first byte of the actual int value
// 0x11 = second byte of the actual int value
totalKm.memory[0] = EEPROM_Read(KM_ADDR);
totalKm.memory[1] = EEPROM_Read(KM_ADDR+1);
// 0xFF is 8 bit, an uint is 2 byte = 16 bit, so we need 0xFFFF
if(totalKm.value == 0xFFFF) {
totalKm.value = 0;
}
do {
// Reads the value of the RA2 Analog knob.
adcInput = ADC_Read(2);
if(shouldUpdateSpeedometer == 1) {
shouldUpdateSpeedometer = 0;
// Update speedometer LCD here
speed(speedBuf, adcInput, &kph);
Lcd_Out(1,1,empty);
Lcd_Out(1,1,"km/t: ");
Lcd_Out(1,7,speedBuf);
}
if(shouldUpdateTotal) {
shouldUpdateTotal = 0;
// Update LCD and save total here
total(totalBuf, &totalKm.value, kph);
EEPROM_Write(KM_ADDR, totalKm.memory[0]);
EEPROM_Write(KM_ADDR+1, totalKm.memory[1]);
Lcd_Out(2,1,empty);
Lcd_Out(2,1, "Total: ");
Lcd_Out(2,8, totalBuf);
}
}while(1);
}