mirror of
https://github.com/qmk/qmk_firmware.git
synced 2026-10-01 14:29:08 +02:00
Merge remote-tracking branch 'origin/develop' into xap
This commit is contained in:
@@ -9,10 +9,10 @@
|
||||
#include "analog.h"
|
||||
|
||||
typedef struct __attribute__((__packed__)) {
|
||||
char magic_numbers[3];
|
||||
uint8_t version_major;
|
||||
uint8_t version_minor;
|
||||
uint8_t version_patch;
|
||||
char magic_numbers[3];
|
||||
uint8_t version_major;
|
||||
uint8_t version_minor;
|
||||
uint8_t version_patch;
|
||||
uint32_t checksum;
|
||||
uint16_t payload_length;
|
||||
} myriad_header_t;
|
||||
@@ -20,34 +20,36 @@ typedef struct __attribute__((__packed__)) {
|
||||
typedef struct __attribute__((__packed__)) {
|
||||
uint16_t vendor_id;
|
||||
uint16_t product_id;
|
||||
uint8_t revision;
|
||||
uint8_t revision;
|
||||
} identity_record_t;
|
||||
|
||||
static bool myriad_reader(uint8_t *data, uint16_t length) {
|
||||
const uint8_t eeprom_address = 0x50; // 1010 000 - NOT shifted for R/W bit
|
||||
const uint16_t i2c_timeout = 100; // in milliseconds
|
||||
const uint8_t eeprom_address = 0x50; // 1010 000 - NOT shifted for R/W bit
|
||||
const uint16_t i2c_timeout = 100; // in milliseconds
|
||||
|
||||
uint8_t num_pages = (length / 256) + 1;
|
||||
uint8_t num_pages = (length / 256) + 1;
|
||||
uint8_t last_page_size = length % 256;
|
||||
|
||||
for (int i = 0; i < num_pages; i++) {
|
||||
uint8_t reg = 0; // We always start on a page boundary, so this is always zero
|
||||
uint8_t reg = 0; // We always start on a page boundary, so this is always zero
|
||||
uint16_t read_length;
|
||||
if (i == num_pages - 1) {
|
||||
read_length = last_page_size;
|
||||
} else {
|
||||
read_length = 256;
|
||||
}
|
||||
i2c_status_t s = i2c_read_register((eeprom_address + i) << 1, reg, &(data[i*256]), read_length, i2c_timeout);
|
||||
if (s != I2C_STATUS_SUCCESS) { return false; }
|
||||
i2c_status_t s = i2c_read_register((eeprom_address + i) << 1, reg, &(data[i * 256]), read_length, i2c_timeout);
|
||||
if (s != I2C_STATUS_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool verify_header(myriad_header_t *header) {
|
||||
char magic_numbers[] = {'M', 'Y', 'R'};
|
||||
uint8_t version_major = 1;
|
||||
uint16_t version_minor = 0;
|
||||
char magic_numbers[] = {'M', 'Y', 'R'};
|
||||
uint8_t version_major = 1;
|
||||
uint16_t version_minor = 0;
|
||||
|
||||
for (int i = 0; i < sizeof(magic_numbers); i++) {
|
||||
// Check that the header starts with 'MYR', indicating that this is indeed a Myriad card.
|
||||
@@ -82,16 +84,15 @@ static bool verify_checksum(uint8_t *data, uint16_t length, uint32_t checksum) {
|
||||
const uint32_t MOD_ADLER = 65521;
|
||||
|
||||
uint32_t a = 1, b = 0;
|
||||
size_t index;
|
||||
|
||||
size_t index;
|
||||
|
||||
// Process each byte of the data in order
|
||||
for (index = 0; index < length; ++index)
|
||||
{
|
||||
for (index = 0; index < length; ++index) {
|
||||
a = (a + data[index]) % MOD_ADLER;
|
||||
b = (b + a) % MOD_ADLER;
|
||||
}
|
||||
uint32_t calculated = ((b << 16) | a);
|
||||
|
||||
|
||||
return calculated == checksum;
|
||||
}
|
||||
|
||||
@@ -108,9 +109,9 @@ static int16_t locate_entry(uint8_t entry_type, uint8_t entry_data_length, uint8
|
||||
while (offset < maximum) {
|
||||
if (data[offset] == entry_type) {
|
||||
// Type matches!
|
||||
if (data[offset+1] == entry_data_length) {
|
||||
if (data[offset + 1] == entry_data_length) {
|
||||
// We found what we are looking for, so return payload reference.
|
||||
return offset+2;
|
||||
return offset + 2;
|
||||
} else {
|
||||
// The entry is the wrong length?
|
||||
return -2;
|
||||
@@ -118,7 +119,7 @@ static int16_t locate_entry(uint8_t entry_type, uint8_t entry_data_length, uint8
|
||||
} else {
|
||||
// No type match, so skip this one
|
||||
// We skip the type byte, the length byte, and any potential data (with length stored in the length byte)
|
||||
offset += 2 + data[offset+1];
|
||||
offset += 2 + data[offset + 1];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,13 +128,15 @@ static int16_t locate_entry(uint8_t entry_type, uint8_t entry_data_length, uint8
|
||||
}
|
||||
|
||||
static bool read_card_identity(uint8_t *data, uint16_t length, identity_record_t *record) {
|
||||
const uint8_t identity_type = 0x01;
|
||||
const uint8_t identity_type = 0x01;
|
||||
const uint8_t entry_data_length = sizeof(identity_record_t);
|
||||
int16_t result = locate_entry(identity_type, entry_data_length, data, 0, length);
|
||||
if (result < 0) { return false; }
|
||||
int16_t result = locate_entry(identity_type, entry_data_length, data, 0, length);
|
||||
if (result < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < sizeof(identity_record_t); i++) {
|
||||
((uint8_t*)record)[i] = data[result + i];
|
||||
((uint8_t *)record)[i] = data[result + i];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -141,27 +144,37 @@ static bool read_card_identity(uint8_t *data, uint16_t length, identity_record_t
|
||||
static myriad_card_t _detect_myriad(void) {
|
||||
gpio_set_pin_input(MYRIAD_PRESENT);
|
||||
wait_ms(100);
|
||||
// The pin has an external pull-up, and a Myriad card shorts it to ground.
|
||||
#ifndef MYRIAD_OVERRIDE_PRESENCE
|
||||
// The pin has an external pull-up, and a Myriad card shorts it to ground.
|
||||
#ifndef MYRIAD_OVERRIDE_PRESENCE
|
||||
if (gpio_read_pin(MYRIAD_PRESENT)) {
|
||||
return NONE;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Attempt to read header
|
||||
myriad_header_t header;
|
||||
if (!myriad_reader((uint8_t*)&header, sizeof(header))) { return INVALID; }
|
||||
if (!verify_header(&header)) { return INVALID; }
|
||||
if (!myriad_reader((uint8_t *)&header, sizeof(header))) {
|
||||
return INVALID;
|
||||
}
|
||||
if (!verify_header(&header)) {
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
// Now that we have determined that the header is valid
|
||||
// and we know the payload length, read the entire thing
|
||||
uint8_t data[2048]; // Guaranteed to be large enough.
|
||||
uint16_t data_size = sizeof(header)+header.payload_length;
|
||||
if (!myriad_reader(data, data_size)) { return INVALID; }
|
||||
if (!verify_checksum(data, data_size, header.checksum)) { return INVALID; }
|
||||
uint8_t data[2048]; // Guaranteed to be large enough.
|
||||
uint16_t data_size = sizeof(header) + header.payload_length;
|
||||
if (!myriad_reader(data, data_size)) {
|
||||
return INVALID;
|
||||
}
|
||||
if (!verify_checksum(data, data_size, header.checksum)) {
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
identity_record_t identity;
|
||||
if (!read_card_identity(data, data_size, &identity)) { return INVALID; }
|
||||
if (!read_card_identity(data, data_size, &identity)) {
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
if (identity.vendor_id == 0x0001 && identity.product_id == 0x0001) {
|
||||
return SKB_ENCODER;
|
||||
@@ -201,7 +214,7 @@ static void myr_encoder_init(void) {
|
||||
}
|
||||
|
||||
static uint16_t myr_joystick_timer;
|
||||
static void myr_joystick_init(void) {
|
||||
static void myr_joystick_init(void) {
|
||||
gpio_set_pin_input_high(MYRIAD_GPIO1); // Press
|
||||
|
||||
myr_joystick_timer = timer_read();
|
||||
@@ -235,7 +248,7 @@ static myriad_card_t myriad_card_init(void) {
|
||||
|
||||
bool myriad_hook_matrix(matrix_row_t current_matrix[]) {
|
||||
myriad_card_t card = myriad_card_init();
|
||||
uint8_t word = 0;
|
||||
uint8_t word = 0;
|
||||
|
||||
if (card == SKB_SWITCHES) {
|
||||
word |= ((!gpio_read_pin(MYRIAD_GPIO3)) & 1) << 0;
|
||||
@@ -252,7 +265,7 @@ bool myriad_hook_matrix(matrix_row_t current_matrix[]) {
|
||||
|
||||
// 5 bytes of on-board keys, so we are the 6th
|
||||
bool matrix_has_changed = current_matrix[5] ^ word;
|
||||
current_matrix[5] = word;
|
||||
current_matrix[5] = word;
|
||||
|
||||
return matrix_has_changed;
|
||||
}
|
||||
@@ -261,16 +274,20 @@ static pin_t encoders_pad_a[NUM_ENCODERS_MAX_PER_SIDE];
|
||||
static pin_t encoders_pad_b[NUM_ENCODERS_MAX_PER_SIDE];
|
||||
|
||||
uint8_t myriad_hook_encoder(uint8_t index, bool pad_b) {
|
||||
if (myriad_card_init() != SKB_ENCODER) { return 0; }
|
||||
if (myriad_card_init() != SKB_ENCODER) {
|
||||
return 0;
|
||||
}
|
||||
// 3 onboard encoders, so we are number 4
|
||||
pin_t pin = pad_b ? encoders_pad_b[index] : encoders_pad_a[index];
|
||||
pin_t pin = pad_b ? encoders_pad_b[index] : encoders_pad_a[index];
|
||||
encoders_pad_a[3] = MYRIAD_GPIO2;
|
||||
encoders_pad_b[3] = MYRIAD_GPIO3;
|
||||
return gpio_read_pin(pin) ? 1 : 0;
|
||||
}
|
||||
|
||||
report_mouse_t pointing_device_driver_get_report(report_mouse_t mouse_report) {
|
||||
if (myriad_card_init() != SKB_JOYSTICK) { return mouse_report; }
|
||||
if (myriad_card_init() != SKB_JOYSTICK) {
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
if (timer_elapsed(myr_joystick_timer) < 10) {
|
||||
wait_ms(2);
|
||||
@@ -286,10 +303,10 @@ report_mouse_t pointing_device_driver_get_report(report_mouse_t mouse_report) {
|
||||
|
||||
// Create a dead zone in the middle where the mouse doesn't move
|
||||
const int16_t dead_zone = 10;
|
||||
if ((y < 0 && y > -1*dead_zone) || (y > 0 && y < dead_zone)) {
|
||||
if ((y < 0 && y > -1 * dead_zone) || (y > 0 && y < dead_zone)) {
|
||||
y = 0;
|
||||
}
|
||||
if ((x < 0 && x > -1*dead_zone) || (x > 0 && x < dead_zone)) {
|
||||
if ((x < 0 && x > -1 * dead_zone) || (x > 0 && x < dead_zone)) {
|
||||
x = 0;
|
||||
}
|
||||
|
||||
@@ -298,10 +315,18 @@ report_mouse_t pointing_device_driver_get_report(report_mouse_t mouse_report) {
|
||||
y = abs(y) * y / 5000;
|
||||
|
||||
// Clamp final value to make sure we don't under/overflow
|
||||
if (y < -127) { y = -127; }
|
||||
if (y > 127) { y = 127; }
|
||||
if (x < -127) { x = -127; }
|
||||
if (x > 127) { x = 127; }
|
||||
if (y < -127) {
|
||||
y = -127;
|
||||
}
|
||||
if (y > 127) {
|
||||
y = 127;
|
||||
}
|
||||
if (x < -127) {
|
||||
x = -127;
|
||||
}
|
||||
if (x > 127) {
|
||||
x = 127;
|
||||
}
|
||||
|
||||
mouse_report.x = x;
|
||||
mouse_report.y = y;
|
||||
@@ -309,7 +334,8 @@ report_mouse_t pointing_device_driver_get_report(report_mouse_t mouse_report) {
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
void pointing_device_driver_init(void) {
|
||||
bool pointing_device_driver_init(void) {
|
||||
gpio_set_pin_input(MYRIAD_ADC1); // Y
|
||||
gpio_set_pin_input(MYRIAD_ADC2); // X
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user