aboutsummaryrefslogtreecommitdiff
path: root/keyboards/atomic/atomic.c
diff options
context:
space:
mode:
authorJack Humbert <jack.humb@gmail.com>2016-06-21 22:39:54 -0400
committerGitHub <noreply@github.com>2016-06-21 22:39:54 -0400
commit649b33d7783cf3021928534b7ae127e0a89e8807 (patch)
treec2b5e0cf8ff4aa2918e3b88ab75dbdb071cc0a1d /keyboards/atomic/atomic.c
parent464c8e274f993d3571fe5ea5e836fe55a3912ffe (diff)
downloadqmk_firmware-649b33d7783cf3021928534b7ae127e0a89e8807.tar.gz
qmk_firmware-649b33d7783cf3021928534b7ae127e0a89e8807.zip
Renames keyboard folder to keyboards, adds couple of tmk's fixes (#432)
* fixes from tmk's repo * rename keyboard to keyboards
Diffstat (limited to 'keyboards/atomic/atomic.c')
-rw-r--r--keyboards/atomic/atomic.c325
1 files changed, 325 insertions, 0 deletions
diff --git a/keyboards/atomic/atomic.c b/keyboards/atomic/atomic.c
new file mode 100644
index 000000000..fa218a48f
--- /dev/null
+++ b/keyboards/atomic/atomic.c
@@ -0,0 +1,325 @@
1#include "atomic.h"
2
3__attribute__ ((weak))
4void matrix_init_user(void) {
5 // leave this function blank - it can be defined in a keymap file
6};
7
8__attribute__ ((weak))
9void matrix_scan_user(void) {
10 // leave this function blank - it can be defined in a keymap file
11}
12
13__attribute__ ((weak))
14bool process_action_user(keyrecord_t *record) {
15 // leave this function blank - it can be defined in a keymap file
16 return true;
17}
18
19__attribute__ ((weak))
20void led_set_user(uint8_t usb_led) {
21 // leave this function blank - it can be defined in a keymap file
22}
23
24void matrix_init_kb(void) {
25 // put your keyboard start-up code here
26 // runs once when the firmware starts up
27
28 MCUCR |= (1<<JTD);
29 MCUCR |= (1<<JTD);
30
31#ifdef BACKLIGHT_ENABLE
32 backlight_init_ports();
33#endif
34
35 // Turn status LED on
36 DDRE |= (1<<6);
37 PORTE |= (1<<6);
38
39 matrix_init_user();
40}
41
42void matrix_scan_kb(void) {
43 // put your looping keyboard code here
44 // runs every cycle (a lot)
45
46 matrix_scan_user();
47}
48
49bool process_action_kb(keyrecord_t *record) {
50 // put your per-action keyboard code here
51 // runs for every action, just before processing by the firmware
52
53 return process_action_user(record);
54}
55
56void led_set_kb(uint8_t usb_led) {
57 // put your keyboard LED indicator (ex: Caps Lock LED) toggling code here
58
59 led_set_user(usb_led);
60}
61
62#ifdef BACKLIGHT_ENABLE
63#define CHANNEL OCR1C
64#define BREATHING_NO_HALT 0
65#define BREATHING_HALT_OFF 1
66#define BREATHING_HALT_ON 2
67
68static uint8_t breath_intensity;
69static uint8_t breath_speed;
70static uint16_t breathing_index;
71static uint8_t breathing_halt;
72
73void backlight_init_ports()
74{
75
76 // Setup PB7 as output and output low.
77 DDRB |= (1<<7);
78 PORTB &= ~(1<<7);
79
80 // Use full 16-bit resolution.
81 ICR1 = 0xFFFF;
82
83 // I could write a wall of text here to explain... but TL;DW
84 // Go read the ATmega32u4 datasheet.
85 // And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on
86
87 // Pin PB7 = OCR1C (Timer 1, Channel C)
88 // Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0
89 // (i.e. start high, go low when counter matches.)
90 // WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0
91 // Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1
92
93 TCCR1A = _BV(COM1C1) | _BV(WGM11); // = 0b00001010;
94 TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
95
96 backlight_init();
97 breathing_defaults();
98}
99
100void backlight_set(uint8_t level)
101{
102 // Prevent backlight blink on lowest level
103 PORTB &= ~(_BV(PORTB7));
104
105 if ( level == 0 )
106 {
107 // Turn off PWM control on PB7, revert to output low.
108 TCCR1A &= ~(_BV(COM1C1));
109
110 // Set the brightness to 0
111 CHANNEL = 0x0;
112 }
113 else if ( level >= BACKLIGHT_LEVELS )
114 {
115 // Turn on PWM control of PB7
116 TCCR1A |= _BV(COM1C1);
117
118 // Set the brightness to max
119 CHANNEL = 0xFFFF;
120 }
121 else
122 {
123 // Turn on PWM control of PB7
124 TCCR1A |= _BV(COM1C1);
125
126 // Set the brightness
127 CHANNEL = 0xFFFF >> ((BACKLIGHT_LEVELS - level) * ((BACKLIGHT_LEVELS + 1) / 2));
128 }
129 breathing_intensity_default();
130}
131
132
133void breathing_enable(void)
134{
135 if (get_backlight_level() == 0)
136 {
137 breathing_index = 0;
138 }
139 else
140 {
141 // Set breathing_index to be at the midpoint (brightest point)
142 breathing_index = 0x20 << breath_speed;
143 }
144
145 breathing_halt = BREATHING_NO_HALT;
146
147 // Enable breathing interrupt
148 TIMSK1 |= _BV(OCIE1A);
149}
150
151void breathing_pulse(void)
152{
153 if (get_backlight_level() == 0)
154 {
155 breathing_index = 0;
156 }
157 else
158 {
159 // Set breathing_index to be at the midpoint + 1 (brightest point)
160 breathing_index = 0x21 << breath_speed;
161 }
162
163 breathing_halt = BREATHING_HALT_ON;
164
165 // Enable breathing interrupt
166 TIMSK1 |= _BV(OCIE1A);
167}
168
169void breathing_disable(void)
170{
171 // Disable breathing interrupt
172 TIMSK1 &= ~_BV(OCIE1A);
173 backlight_set(get_backlight_level());
174}
175
176void breathing_self_disable(void)
177{
178 if (get_backlight_level() == 0)
179 {
180 breathing_halt = BREATHING_HALT_OFF;
181 }
182 else
183 {
184 breathing_halt = BREATHING_HALT_ON;
185 }
186
187 //backlight_set(get_backlight_level());
188}
189
190void breathing_toggle(void)
191{
192 if (!is_breathing())
193 {
194 if (get_backlight_level() == 0)
195 {
196 breathing_index = 0;
197 }
198 else
199 {
200 // Set breathing_index to be at the midpoint + 1 (brightest point)
201 breathing_index = 0x21 << breath_speed;
202 }
203
204 breathing_halt = BREATHING_NO_HALT;
205 }
206
207 // Toggle breathing interrupt
208 TIMSK1 ^= _BV(OCIE1A);
209
210 // Restore backlight level
211 if (!is_breathing())
212 {
213 backlight_set(get_backlight_level());
214 }
215}
216
217bool is_breathing(void)
218{
219 return (TIMSK1 && _BV(OCIE1A));
220}
221
222void breathing_intensity_default(void)
223{
224 //breath_intensity = (uint8_t)((uint16_t)100 * (uint16_t)get_backlight_level() / (uint16_t)BACKLIGHT_LEVELS);
225 breath_intensity = ((BACKLIGHT_LEVELS - get_backlight_level()) * ((BACKLIGHT_LEVELS + 1) / 2));
226}
227
228void breathing_intensity_set(uint8_t value)
229{
230 breath_intensity = value;
231}
232
233void breathing_speed_default(void)
234{
235 breath_speed = 4;
236}
237
238void breathing_speed_set(uint8_t value)
239{
240 bool is_breathing_now = is_breathing();
241 uint8_t old_breath_speed = breath_speed;
242
243 if (is_breathing_now)
244 {
245 // Disable breathing interrupt
246 TIMSK1 &= ~_BV(OCIE1A);
247 }
248
249 breath_speed = value;
250
251 if (is_breathing_now)
252 {
253 // Adjust index to account for new speed
254 breathing_index = (( (uint8_t)( (breathing_index) >> old_breath_speed ) ) & 0x3F) << breath_speed;
255
256 // Enable breathing interrupt
257 TIMSK1 |= _BV(OCIE1A);
258 }
259
260}
261
262void breathing_speed_inc(uint8_t value)
263{
264 if ((uint16_t)(breath_speed - value) > 10 )
265 {
266 breathing_speed_set(0);
267 }
268 else
269 {
270 breathing_speed_set(breath_speed - value);
271 }
272}
273
274void breathing_speed_dec(uint8_t value)
275{
276 if ((uint16_t)(breath_speed + value) > 10 )
277 {
278 breathing_speed_set(10);
279 }
280 else
281 {
282 breathing_speed_set(breath_speed + value);
283 }
284}
285
286void breathing_defaults(void)
287{
288 breathing_intensity_default();
289 breathing_speed_default();
290 breathing_halt = BREATHING_NO_HALT;
291}
292
293/* Breathing Sleep LED brighness(PWM On period) table
294 * (64[steps] * 4[duration]) / 64[PWM periods/s] = 4 second breath cycle
295 *
296 * http://www.wolframalpha.com/input/?i=%28sin%28+x%2F64*pi%29**8+*+255%2C+x%3D0+to+63
297 * (0..63).each {|x| p ((sin(x/64.0*PI)**8)*255).to_i }
298 */
299static const uint8_t breathing_table[64] PROGMEM = {
300 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 10,
301 15, 23, 32, 44, 58, 74, 93, 113, 135, 157, 179, 199, 218, 233, 245, 252,
302255, 252, 245, 233, 218, 199, 179, 157, 135, 113, 93, 74, 58, 44, 32, 23,
303 15, 10, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
304};
305
306ISR(TIMER1_COMPA_vect)
307{
308 // CHANNEL = (pgm_read_byte(&breathing_table[ ( (uint8_t)( (breathing_index++) >> breath_speed ) ) & 0x3F ] )) * breath_intensity;
309
310
311 uint8_t local_index = ( (uint8_t)( (breathing_index++) >> breath_speed ) ) & 0x3F;
312
313 if (((breathing_halt == BREATHING_HALT_ON) && (local_index == 0x20)) || ((breathing_halt == BREATHING_HALT_OFF) && (local_index == 0x3F)))
314 {
315 // Disable breathing interrupt
316 TIMSK1 &= ~_BV(OCIE1A);
317 }
318
319 CHANNEL = (uint16_t)(((uint16_t)pgm_read_byte(&breathing_table[local_index]) * 257)) >> breath_intensity;
320
321}
322
323
324
325#endif \ No newline at end of file