-
Notifications
You must be signed in to change notification settings - Fork 0
/
atmegaClock.h
executable file
·250 lines (193 loc) · 4.52 KB
/
atmegaClock.h
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
#ifndef ATMEGA_CLOCK_H
#define ATMEGA_CLOCK_H
// ATmega328p clock with Li-ion battery management
//
// Schematics can be found here:
// https://easyeda.com/Yulay/atmega328p-clock_copy
//
// Simple clock, based on 32768 Hz crystal oscillator
// with automatic brightness control and power saving modes
// for backup Li-ion 18600 type battery.
// Display TM1637 7-segment LED i2c module
// Fine clock calibration can be achieved by changing clock correction value.
/*
Running on internal 8 MHz clock
CPU Clock Freq = 1 MHz
Main prescaler = 8
Asynchronous clock 32768 Hz on Timer2
PB6 : TOSC1
PB7 : TOSC2
Input ports
PD2 : Inc Minutes
PD3 : Inc Hours
PD4 : Time Correction Mode
PD5 : Snoose
PD6 : Alarm Clock Set Mode
PD7 : Alarm On/Off
PC1 : Speaker_N output
PC2 : Speaker_P output
PC3 : Power Control TM1637
Timer0 1000000 Hz / 256
Timer1 1000000 Hz / 256 / 32 = ~122 Hz
I2C
PC4 : SDA
PC5 : SCL
ADC
ADC0 : Measure ambient light level with Vref = Vcc
ADC BG: Measure bandgap voltage 1.1V with Vref = Vcc ==> measure Vcc
SLEEP MODE
Wakeup sources
PCINT2 pin change
Timer2 1 Hz
*/
#ifndef F_CPU
#define F_CPU 1000000
#endif
#include <stdint.h>
#include <stdbool.h>
#include <avr/io.h>
#include "tm1637.h"
#define INC_M_IN PORTD2
#define INC_H_IN PORTD3
#define TIME_IN PORTD4
#define SNOOSE_IN PORTD5
#define ALARM_IN PORTD6
#define ALARM_ON PORTD7
#define INPUT_AVERAGING 5
#define kInputTime _BV(TIME_IN)
#define kInputAlarm _BV(ALARM_IN)
#define kInputSnoose _BV(SNOOSE_IN)
#define kCmdMask (kInputTime | kInputAlarm | kInputSnoose)
#define kInputMinutes _BV(INC_M_IN)
#define kInputHours _BV(INC_H_IN)
#define kResetSecs (kInputMinutes | kInputHours)
#define SPEAKER_N PC1
#define SPEAKER_P PC2
#define POWER_TM1637 PC3
#define ADC_VREF_VCC 0 // Vcc as voltage reference
#define ADC_VREF_1V1 _BV(REFS1) // 1.1V internal VREF without external capacitor
#define ADC_VREF_2V56 (_BV(REFS2) | _BV(REFS1)) // 2.56V internal VREF without external capacitor
#define VBANDGAP_1v1_IN (_BV(MUX3) | _BV(MUX2)) //0x0c 1.1V bandgap voltage source
#define TEMPERATURE_IN (_BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0)) //0x07 ADC4 internal temperature
#define ADC_LEFT_JUSTIFIED _BV(ADLAR) //0x20 - left justified, so we can use ADCH as a 8 bit result
#define VCC_ADC 255
#define BG_VOLTAGE 11/10
#define VOLTAGE(x) (255 - 96 - ((VCC_ADC * BG_VOLTAGE) / x)
#define BATTERY_FULL 92 // 4.2V
#define BATTERY_NORMAL 87 // 3.9V
#define BATTERY_DISCHARGING 83 // 3.7V
enum Notes // First Octave
{
noteC4 = 239, // 261.63 Hz
noteD4 = 213, // 293.66,
noteE4 = 190, // 329.63,
noteF4 = 179, // 349.23,
noteG4 = 156, // 392.00,
noteA4 = 142, // 440.00,
noteB4 = 127, // 493.88
};
void Setup();
void DisplayTime();
void DisplayAlarm();
void DisplayClockCorrection();
inline void Timer1_Enable()
{
TIMSK1 |= _BV(OCIE1A);
}
inline void Timer1_Disable()
{
TIMSK1 &= ~_BV(OCIE1A);
}
inline void StartWaitForRtcTick()
{
TCCR2B = _BV(CS22) | _BV(CS20); //prescaler 128}
}
inline void WaitForRtcTick()
{
while (ASSR & (_BV(TCN2UB) | _BV(OCR2BUB) | _BV(TCR2BUB))) //Wait until TC2 is updated
{}
}
inline void ADC_Enable()
{
PRR &= ~_BV(PRADC);
}
inline void ADC_Disable()
{
PRR |= _BV(PRADC);
}
inline void ADC_Start()
{
ADC_Enable();
ADCSRA |= _BV(ADSC);
}
inline void AdcIn_Voltage()
{
ADMUX = _BV(REFS0) | _BV(ADLAR) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
}
inline void AdcIn_Light()
{
ADMUX = _BV(REFS0) | _BV(ADLAR);
}
inline void Buttons_Enable()
{
PCICR |= _BV(PCIE2);
}
inline void Buttons_Disable()
{
PCICR &= ~_BV(PCIE2);
}
inline void Display_Initialize()
{
TM1637_enable(1);
}
inline void Display_Shutdown()
{
TM1637_enable(0);
}
inline uint8_t Buttons_Read()
{
return (~PIND) & 0xfc; //negative logic
}
inline void Display_On()
{
PORTC |= _BV(POWER_TM1637);
}
inline void Display_Off()
{
PORTC &= ~_BV(POWER_TM1637);
}
inline void SetLED(bool v)
{
if(v)
{
PORTB |= _BV(PORTB5);
}
else
{
PORTB &= ~_BV(PORTB5);
}
}
inline void ToggleLED()
{
PINB |= _BV(PORTB5); //toggle output port
}
inline void Speaker_On()
{
TIMSK0 |= _BV(OCIE0A) | _BV(OCIE0B);
PORTC |= _BV(SPEAKER_P);
}
inline void Speaker_Off()
{
TIMSK0 &= ~(_BV(OCIE0A) | _BV(OCIE0B));
PORTC &= ~(_BV(SPEAKER_N) | _BV(SPEAKER_P));
}
inline void Speaker_Toggle()
{
PINC = _BV(SPEAKER_N) | _BV(SPEAKER_P); //toggle outputs
}
inline void Speaker_Freq(uint8_t note)
{
OCR0A = note;
OCR0B = note/2;
}
#endif //ATMEGA_CLOCK_H