aboutsummaryrefslogtreecommitdiffstats
path: root/quantum/process_keycode/process_unicodemap.c
blob: 75f35112b133db91c16d75a966a7b76d5afb2e12 (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
/* Copyright 2017 Jack Humbert
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "process_unicodemap.h"
#include "process_unicode_common.h"

__attribute__((weak))
const uint32_t PROGMEM unicode_map[] = {
};

void register_hex32(uint32_t hex) {
  bool onzerostart = true;
  for(int i = 7; i >= 0; i--) {
    if (i <= 3) {
      onzerostart = false;
    }
    uint8_t digit = ((hex >> (i*4)) & 0xF);
    if (digit == 0) {
      if (!onzerostart) {
        register_code(hex_to_keycode(digit));
        unregister_code(hex_to_keycode(digit));
      }
    } else {
      register_code(hex_to_keycode(digit));
      unregister_code(hex_to_keycode(digit));
      onzerostart = false;
    }
  }
}

__attribute__((weak))
void unicode_map_input_error() {}

bool process_unicode_map(uint16_t keycode, keyrecord_t *record) {
  uint8_t input_mode = get_unicode_input_mode();
  if ((keycode & QK_UNICODE_MAP) == QK_UNICODE_MAP && record->event.pressed) {
    const uint32_t* map = unicode_map;
    uint16_t index = keycode - QK_UNICODE_MAP;
    uint32_t code = pgm_read_dword(&map[index]);
    if (code > 0xFFFF && code <= 0x10ffff && input_mode == UC_OSX) {
      // Convert to UTF-16 surrogate pair
      code -= 0x10000;
      uint32_t lo = code & 0x3ff;
      uint32_t hi = (code & 0xffc00) >> 10;
      unicode_input_start();
      register_hex32(hi + 0xd800);
      register_hex32(lo + 0xdc00);
      unicode_input_finish();
    } else if ((code > 0x10ffff && input_mode == UC_OSX) || (code > 0xFFFFF && input_mode == UC_LNX)) {
      // when character is out of range supported by the OS
      unicode_map_input_error();
    } else {
      unicode_input_start();
      register_hex32(code);
      unicode_input_finish();
    }
  }
  return true;
}
>, 0x34); if (parity) { data_hi(); } else { data_lo(); } WAIT(clock_lo, 100, 0x35); /* Stop bit */ WAIT(clock_hi, 100, 0x34); data_hi(); /* End */ WAIT(data_lo, 100, 0x36); idle(); IBM4704_INT_ON(); return 0; ERROR: idle(); if (ibm4704_error > 0x30) { xprintf("S:%02X ", ibm4704_error); } IBM4704_INT_ON(); return -1; } /* wait forever to receive data */ uint8_t ibm4704_recv_response(void) { while (!rbuf_has_data()) { _delay_ms(1); } return rbuf_dequeue(); } uint8_t ibm4704_recv(void) { if (rbuf_has_data()) { return rbuf_dequeue(); } else { return -1; } } /* Keyboard to Host ---------------- Data bits are LSB first and Parity is odd. Clock has around 60us high and 30us low part. ____ __ __ __ __ __ __ __ __ __ _______ Clock \_____/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ Data ____/ X____X____X____X____X____X____X____X____X____X________ Start 0 1 2 3 4 5 6 7 P Stop Start bit: can be long as 300-350us. Inhibit: Pull Data line down to inhibit keyboard to send. Timing: Host reads bit while Clock is hi.(rising edge) Stop bit: Keyboard pulls down Data line to lo after 9th clock. */ ISR(IBM4704_INT_VECT) { static enum { BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7, PARITY, STOP } state = BIT0; // LSB first static uint8_t data = 0; // Odd parity static uint8_t parity = false; ibm4704_error = 0; switch (state) { case BIT0: case BIT1: case BIT2: case BIT3: case BIT4: case BIT5: case BIT6: case BIT7: data >>= 1; if (data_in()) { data |= 0x80; parity = !parity; } break; case PARITY: if (data_in()) { parity = !parity; } if (!parity) goto ERROR; break; case STOP: // Data:Low WAIT(data_lo, 100, state); rbuf_enqueue(data); ibm4704_error = IBM4704_ERR_NONE; goto DONE; break; default: goto ERROR; } state++; goto RETURN; ERROR: ibm4704_error = state; while (ibm4704_send(0xFE)) _delay_ms(1); // resend xprintf("R:%02X%02X\n", state, data); DONE: state = BIT0; data = 0; parity = false; RETURN: return; }