]> git.donarmstrong.com Git - qmk_firmware.git/blob - keyboards/sol/common/knob_v2.c
Fixup the clueboard 66 info.json
[qmk_firmware.git] / keyboards / sol / common / knob_v2.c
1 #include "knob_v2.h"
2
3 bool knob_prev_a = false;
4 static knob_report_t knob_report = {.dir = 0, .phase = 0};
5
6 void knob_init(void) {
7     // I use pins D1 (ISR1) & D4 for a knob.
8
9     // Set pin mode for D4 as input.
10     DDRD &= ~(0UL << ENCODER_PIN_2);
11
12     // Enable internal pull-up for D4.
13     // This is done by "writing" 1 to a pin that has its mode set to input.
14     PORTD |= (1 << ENCODER_PIN_2);
15
16     // Enable interrupt for D1
17     // For more info on the below flags see this awesome section 11.1 (pages 89-90) here:
18     // https://cdn-shop.adafruit.com/datasheets/atmel-7766-8-bit-avr-atmega16u4-32u4_datasheet.pdf
19     // Set pin mode & pull-up.
20     DDRD &= ~(0UL << ENCODER_PIN_1);
21     PORTD |= (1UL << ENCODER_PIN_1);
22
23     // INT:    33221100
24     EICRA |= 0b00010000;  // 0b01 - any edge
25     // INT:     6  3210
26     EIMSK |= 0b00000100;
27 }
28
29 ISR(ENCODER_INT) {
30     bool a = PIND & (1 << ENCODER_PIN_1);
31
32     if (knob_prev_a != a) {
33         // "A" channel has REALLY changed.
34         knob_report.phase = a;
35         knob_prev_a = a;
36         bool b = PIND & (1 << ENCODER_PIN_2);
37         if (a == b) {
38             // Halfway through CCW rotation (A == B)
39             //
40             //         +---YOU ARE HERE (A=1, B=1)
41             //         |     +---OR HERE (A=0, B=0)
42             //         |     |
43             //         v     v
44             // A: _____/^^^^^\__
45             // B: __/^^^^^\_____
46             knob_report.dir++;
47         } else {
48             // Halfway through CW rotation (A != B)
49             //
50             //         +---YOU ARE HERE (A=1, B=0)
51             //         |     +---OR HERE (A=0, B=1)
52             //         |     |
53             //         v     v
54             // A: _____/^^^^^\_____
55             // B: ________/^^^^^\__
56             knob_report.dir--;
57         }
58     }
59 }
60
61 knob_report_t knob_report_read(void) {
62     // Return knob report.
63     return knob_report;
64 }
65
66 void knob_report_reset(void) {
67     // Call this ASAP once you've processed the previous knob report.
68     // TODO: This should probably be called within `knob_report_read`.
69     knob_report.dir = 0;
70     knob_report.phase = 0;
71 }