-
Notifications
You must be signed in to change notification settings - Fork 0
/
calculator.c
141 lines (128 loc) · 2.62 KB
/
calculator.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
/* Stjepan Udovičić <[email protected]> */
/* Calculator made for ATmega16 uP on EasyAVR 5A board */
#include <avr/io.h>
#include <util/delay.h>
#include <inttypes.h>
uint16_t count[3];
uint8_t state[2];
uint8_t dot; // wasted 7 bits
void inic(void);
uint8_t sseg(uint8_t);
void disp_n(uint16_t);
void disp(uint8_t, uint8_t);
uint8_t button(volatile uint8_t *, uint8_t);
int main(void) {
inic();
uint8_t i,j,k;
j=0;k=0;state[1]=0;state[1]=0;dot=0;
while (j<2) {
disp_n(count[j]); // display curent number
for (i=0;i<8;i++) // try to read number
if ( (button( &PINA, i)) && k<4 ) {
count[j]= (count[j] * 10) + i;
k++;
}
for (i=0;i<8;i++) // try to read operation
if (button( &PIND, i)) {
if (!j) count[2]=i;
j++;k=0;
}
}
// exec. statement
j=count[2];
switch(j) {
case 0: // +
count[2]=count[0]+count[1];
break;
case 1: // -
count[2]=count[0]-count[1];
break;
case 2: // *
count[2]=count[0]*count[1];
break;
case 3: // /
count[2]=(count[0]*10)/count[1];
if (count[2] & 1)
dot=1;
else
count[2]/=10;
break;
case 4: // exp( num1, num2)
if (count[0]==0)
count[2]=0;
else if (count[1]==0)
count[2]=1;
else {
count[2]=count[0];
for (i=0;i<count[1]-1;i++) count[2]*=count[0];
}
break;
}
//display result
while(1) disp_n(count[2]);
return 0;
}
uint8_t button(volatile uint8_t *port, uint8_t pin) {
uint8_t i = 1;
if (*port == PINA) i=0;
if (*port & (1 << pin )) {
if (!(state[i] & (1 << pin))) {
_delay_ms(10);
if (*port & (1 << pin )) {
state[i] |= (1 << pin);
return 1;
}
}
} else
state[i] &= ~(1 << pin);
return 0;
}
void inic(void) {
/* port initialization*/
DDRA = 0x00;
DDRB = 0xff;
DDRC = 0xff;
DDRD = 0x00;
PORTA = 0xff;
PORTD = 0xff;
PORTB = 0;
PORTC = 0;
}
uint8_t sseg(uint8_t sseg_x) {
/* converts uint8_t to 7seg code */
switch(sseg_x) {
case 0 : return 0x3F;
case 1 : return 0x06;
case 2 : return 0x5B;
case 3 : return 0x4F;
case 4 : return 0x66;
case 5 : return 0x6D;
case 6 : return 0x7D;
case 7 : return 0x07;
case 8 : return 0x7F;
case 9 : return 0x6F;
default: return 0xAA;
}
return 0xAA;
}
void disp_n(uint16_t num) {
/* display uint8_t on 4 7seg displays */
uint8_t i,led[4];
if (num <= 9999) {
led[3]=num/1000;
led[2]=(num%1000)/100;
led[1]=(num%100)/10;
led[0]=num%10;
} else for (i=0;i<4;i++)
disp(i,10);
for (i=0;i<4;i++)
disp(i,led[i]);
}
void disp(uint8_t led, uint8_t num) {
/* display single number on 7seg display */
PORTB = 1 << led;
PORTC = sseg(num);
if (dot && led == 1) PORTC |= 0x80;
_delay_ms(10);
PORTC = 0;
}