-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclock.c
More file actions
174 lines (144 loc) · 3.21 KB
/
clock.c
File metadata and controls
174 lines (144 loc) · 3.21 KB
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
#include <avr/io.h>
#include <util/delay.h>
#include "usi_i2c_master.h"
#define SPICS PB1
#define SPIDATA PB4
#define SPICLK PB3
#define SPIPORT PORTB
#define SPIDDR DDRB
#define SPIIN PINB
#define RTC_SEC 0x81
#define RTC_MIN 0x83
#define RTC_HOUR 0x85
#define IO_IODIRA 0x00u
#define IO_IODIRB 0x01u
#define IO_IOPOLA 0x02u
#define IO_IOPOLB 0x03u
#define IO_GPINTENA 0x04u
#define IO_GPINTENB 0x05u
#define IO_DEFVALA 0x06u
#define IO_DEFVALB 0x07u
#define IO_INTCONA 0x08u
#define IO_INTCONB 0x09u
#define IO_IOCON 0x0au
#define IO_GPPUA 0x0cu
#define IO_GPPUB 0x0du
#define IO_INTFA 0x0eu
#define IO_INTFB 0x0fu
#define IO_INTCAPA 0x10u
#define IO_INTCAPB 0x11u
#define IO_GPIOA 0x12u
#define IO_GPIOB 0x13u
#define IO_OLATA 0x14u
#define IO_OLATB 0x15u
uint8_t bcd_decode(uint8_t value)
{
return (value & 0x0f) + ((value & 0xf0) >> 4) * 10;
}
void rtc_init()
{
SPIDDR |= (1 << SPICLK) | (1 << SPICS);
SPIPORT |= (1 << SPIDATA);
}
void rtc_clk_pulse()
{
SPIPORT |= (1 << SPICLK);
_delay_us(100);
SPIPORT &= ~(1 << SPICLK);
_delay_us(100);
}
void rtc_begin()
{
SPIPORT |= (1 << SPICS);
}
void rtc_end()
{
SPIPORT &= ~(1 << SPICS);
}
void rtc_write_octet(uint8_t value)
{
SPIDDR |= (1 << SPIDATA);
for (uint8_t i = 0; i < 8; i++)
{
if (value & (1 << i))
SPIPORT |= (1 << SPIDATA);
else
SPIPORT &= ~(1 << SPIDATA);
rtc_clk_pulse();
}
SPIDDR &= ~(1 << SPIDATA);
SPIPORT |= (1 << SPIDATA);
}
uint8_t rtc_read_octet()
{
uint8_t value = 0;
for (uint8_t i = 0; i < 8; i++)
{
value |= ((SPIIN & (1 << SPIDATA)) >> SPIDATA) << i;
rtc_clk_pulse();
}
return value;
}
uint8_t rtc_octet_transaction(uint8_t cmd, uint8_t mask)
{
rtc_begin();
rtc_write_octet(cmd);
uint8_t value = rtc_read_octet();
rtc_end();
return bcd_decode(value & mask);
}
#define IO_ADDRESS 0x20u
char io_set_reg(uint8_t reg, uint8_t value)
{
uint8_t buf[3] = {IO_ADDRESS << 1, reg, value};
return USI_I2C_Master_Start_Transmission(buf, 3, 1);
}
char io_get_reg(uint8_t reg, uint8_t* value)
{
uint8_t buf[2] = {IO_ADDRESS << 1, reg};
char e = USI_I2C_Master_Start_Transmission(buf, 2, 0);
if (!e) return e;
buf[0] |= 0x1;
e = USI_I2C_Master_Start_Transmission(buf, 2, 1);
if (!e) return e;
*value = buf[1];
return e;
}
typedef union
{
struct
{
unsigned sec : 6;
unsigned min : 6;
unsigned hour : 4;
};
struct
{
uint8_t latchA;
uint8_t latchB;
};
} Output;
int main()
{
PORT_USI |= (1 << PIN_USI_SDA) | (1 << PIN_USI_SCL);
DDR_USI &= ~((1 << PIN_USI_SDA) | (1 << PIN_USI_SCL));
USIDR = 0xFF;
USICR = (1 << USIWM1) | (1 << USICS1) | (1 << USICLK);
USISR = (1 << USISIF) | (1 << USIOIF) | (1 << USIPF) | (1 << USIDC);
rtc_init();
_delay_ms(100);
io_set_reg(IO_IODIRA, 0);
io_set_reg(IO_IODIRB, 0);
while(1)
{
_delay_ms(20);
uint8_t sec = rtc_octet_transaction(RTC_SEC, 0x7f);
uint8_t min = rtc_octet_transaction(RTC_MIN, 0x7f);
uint8_t hour = rtc_octet_transaction(RTC_HOUR, 0x3f);
if (hour >= 12) hour -= 12;
if (hour == 0) hour = 12;
Output output = { .sec = sec, .min = min, .hour = hour };
io_set_reg(IO_OLATA, output.latchA);
io_set_reg(IO_OLATB, output.latchB);
}
}