summaryrefslogtreecommitdiffstats
path: root/quantum/split_common/split_util.c
blob: e4475c535675be58df1f0fcf8d5ff1b7b58fd6ee (plain)
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
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/power.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#include "split_util.h"
#include "matrix.h"
#include "keyboard.h"
#include "config.h"
#include "timer.h"
#include "split_flags.h"

#ifdef BACKLIGHT_ENABLE
#   include "backlight.h"
#endif

#ifdef SPLIT_HAND_PIN
#   include "pincontrol.h"
#endif

#if defined(USE_I2C) || defined(EH)
#  include "i2c.h"
#endif

volatile bool isLeftHand = true;

volatile uint8_t setTries = 0;

static void setup_handedness(void) {
  #ifdef SPLIT_HAND_PIN
    // Test pin SPLIT_HAND_PIN for High/Low, if low it's right hand
    pinMode(SPLIT_HAND_PIN, PinDirectionInput);
    isLeftHand = digitalRead(SPLIT_HAND_PIN);
  #else
    #ifdef EE_HANDS
      isLeftHand = eeprom_read_byte(EECONFIG_HANDEDNESS);
    #else
      // I2C_MASTER_RIGHT is deprecated, use MASTER_RIGHT instead, since this works for both serial and i2c
      #if defined(I2C_MASTER_RIGHT) || defined(MASTER_RIGHT)
        isLeftHand = !has_usb();
      #else
        isLeftHand = has_usb();
      #endif
    #endif
  #endif
}

static void keyboard_master_setup(void) {
#if defined(USE_I2C) || defined(EH)
  i2c_master_init();
  #ifdef SSD1306OLED
    matrix_master_OLED_init ();
  #endif
#else
  serial_master_init();
#endif

    // For master the Backlight info needs to be sent on startup
    // Otherwise the salve won't start with the proper info until an update
    BACKLIT_DIRTY = true;
}

static void keyboard_slave_setup(void) {
  timer_init();
#if defined(USE_I2C) || defined(EH)
    i2c_slave_init(SLAVE_I2C_ADDRESS);
#else
    serial_slave_init();
#endif
}

bool has_usb(void) {
   USBCON |= (1 << OTGPADE); //enables VBUS pad
   _delay_us(5);
   return (USBSTA & (1<<VBUS));  //checks state of VBUS
}

void split_keyboard_setup(void) {
   setup_handedness();

   if (has_usb()) {
      keyboard_master_setup();
   } else {
      keyboard_slave_setup();
   }
   sei();
}

void keyboard_slave_loop(void) {
   matrix_init();

   //Init RGB
   #ifdef RGBLIGHT_ENABLE
      rgblight_init();
   #endif

   while (1) {
    // Matrix Slave Scan
    matrix_slave_scan();

    // Read Backlight Info
    #ifdef BACKLIGHT_ENABLE
        #ifdef USE_I2C
            if (BACKLIT_DIRTY) {
                backlight_set(i2c_slave_buffer[I2C_BACKLIT_START]);
                BACKLIT_DIRTY = false;
            }
        #else // USE_SERIAL
            backlight_set(serial_m2s_buffer.backlight_level);
        #endif
    #endif
    // Read RGB Info
    #ifdef RGBLIGHT_ENABLE
        #ifdef USE_I2C
            if (RGB_DIRTY) {
                // Disable interupts (RGB data is big)
                cli();
                // Create new DWORD for RGB data
                uint32_t dword;

                // Fill the new DWORD with the data that was sent over
                uint8_t *dword_dat = (uint8_t *)(&dword);
                for (int i = 0; i < 4; i++) {
                    dword_dat[i] = i2c_slave_buffer[I2C_RGB_START+i];
                }

                // Update the RGB now with the new data and set RGB_DIRTY to false
                rgblight_update_dword(dword);
                RGB_DIRTY = false;
                // Re-enable interupts now that RGB is set
                sei();
            }
        #else // USE_SERIAL
          #ifdef RGBLIGHT_SPLIT
            // Add serial implementation for RGB here
          #endif
        #endif
    #endif
   }
}

// this code runs before the usb and keyboard is initialized
void matrix_setup(void) {
    split_keyboard_setup();

    if (!has_usb()) {
        //rgblight_init();
        keyboard_slave_loop();
    }
}