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