Merge pull request #994 from keyboardio/f/driver/keyscanner/model01
Integrate KeyboardioScanner as a driverpull/998/head
commit
448dd47ac2
@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright © 2015 Jesse Vincent <jesse@fsck.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
@ -0,0 +1,214 @@
|
|||||||
|
/* kaleidoscope::driver::keyboardio::Model01Side
|
||||||
|
* Copyright (C) 2015-2020 Keyboard.io, Inc
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KALEIDOSCOPE_VIRTUAL_BUILD
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "Model01Side.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "kaleidoscope/device/keyboardio/twi.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "kaleidoscope/driver/color/GammaCorrection.h"
|
||||||
|
|
||||||
|
namespace kaleidoscope {
|
||||||
|
namespace driver {
|
||||||
|
namespace keyboardio {
|
||||||
|
|
||||||
|
#define SCANNER_I2C_ADDR_BASE 0x58
|
||||||
|
#define ELEMENTS(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||||
|
|
||||||
|
uint8_t twi_uninitialized = 1;
|
||||||
|
|
||||||
|
Model01Side::Model01Side(byte setAd01) {
|
||||||
|
ad01 = setAd01;
|
||||||
|
addr = SCANNER_I2C_ADDR_BASE | ad01;
|
||||||
|
if (twi_uninitialized--) {
|
||||||
|
twi_init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the relative controller addresss. The expected range is 0-3
|
||||||
|
uint8_t Model01Side::controllerAddress() {
|
||||||
|
return ad01;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the keyscan interval. We currently do three reads.
|
||||||
|
// before declaring a key event debounced.
|
||||||
|
//
|
||||||
|
// Takes an integer value representing a counter.
|
||||||
|
//
|
||||||
|
// 0 - 0.1-0.25ms
|
||||||
|
// 1 - 0.125ms
|
||||||
|
// 10 - 0.35ms
|
||||||
|
// 25 - 0.8ms
|
||||||
|
// 50 - 1.6ms
|
||||||
|
// 100 - 3.15ms
|
||||||
|
//
|
||||||
|
// You should think of this as the _minimum_ keyscan interval.
|
||||||
|
// LED updates can cause a bit of jitter.
|
||||||
|
//
|
||||||
|
// returns the Wire.endTransmission code (0 = success)
|
||||||
|
// https://www.arduino.cc/en/Reference/WireEndTransmission
|
||||||
|
byte Model01Side::setKeyscanInterval(byte delay) {
|
||||||
|
uint8_t data[] = {TWI_CMD_KEYSCAN_INTERVAL, delay};
|
||||||
|
uint8_t result = twi_writeTo(addr, data, ELEMENTS(data), 1, 0);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// returns -1 on error, otherwise returns the scanner version integer
|
||||||
|
int Model01Side::readVersion() {
|
||||||
|
return readRegister(TWI_CMD_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns -1 on error, otherwise returns the scanner keyscan interval
|
||||||
|
int Model01Side::readKeyscanInterval() {
|
||||||
|
return readRegister(TWI_CMD_KEYSCAN_INTERVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// returns -1 on error, otherwise returns the LED SPI Frequncy
|
||||||
|
int Model01Side::readLEDSPIFrequency() {
|
||||||
|
return readRegister(TWI_CMD_LED_SPI_FREQUENCY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the LED SPI Frequency. See wire-protocol-constants.h for
|
||||||
|
// values.
|
||||||
|
//
|
||||||
|
// returns the Wire.endTransmission code (0 = success)
|
||||||
|
// https://www.arduino.cc/en/Reference/WireEndTransmission
|
||||||
|
byte Model01Side::setLEDSPIFrequency(byte frequency) {
|
||||||
|
uint8_t data[] = {TWI_CMD_LED_SPI_FREQUENCY, frequency};
|
||||||
|
uint8_t result = twi_writeTo(addr, data, ELEMENTS(data), 1, 0);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int Model01Side::readRegister(uint8_t cmd) {
|
||||||
|
|
||||||
|
byte return_value = 0;
|
||||||
|
|
||||||
|
uint8_t data[] = {cmd};
|
||||||
|
uint8_t result = twi_writeTo(addr, data, ELEMENTS(data), 1, 0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
delayMicroseconds(15); // We may be able to drop this in the future
|
||||||
|
// but will need to verify with correctly
|
||||||
|
// sized pull-ups on both the left and right
|
||||||
|
// hands' i2c SDA and SCL lines
|
||||||
|
|
||||||
|
uint8_t rxBuffer[1];
|
||||||
|
|
||||||
|
// perform blocking read into buffer
|
||||||
|
uint8_t read = twi_readFrom(addr, rxBuffer, ELEMENTS(rxBuffer), true);
|
||||||
|
if (read > 0) {
|
||||||
|
return rxBuffer[0];
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// gives information on the key that was just pressed or released.
|
||||||
|
bool Model01Side::readKeys() {
|
||||||
|
|
||||||
|
uint8_t rxBuffer[5];
|
||||||
|
|
||||||
|
// perform blocking read into buffer
|
||||||
|
uint8_t read = twi_readFrom(addr, rxBuffer, ELEMENTS(rxBuffer), true);
|
||||||
|
if (rxBuffer[0] == TWI_REPLY_KEYDATA) {
|
||||||
|
keyData.rows[0] = rxBuffer[1];
|
||||||
|
keyData.rows[1] = rxBuffer[2];
|
||||||
|
keyData.rows[2] = rxBuffer[3];
|
||||||
|
keyData.rows[3] = rxBuffer[4];
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keydata_t Model01Side::getKeyData() {
|
||||||
|
return keyData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model01Side::sendLEDData() {
|
||||||
|
sendLEDBank(nextLEDBank++);
|
||||||
|
if (nextLEDBank == LED_BANKS) {
|
||||||
|
nextLEDBank = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto constexpr gamma8 = kaleidoscope::driver::color::gamma_correction;
|
||||||
|
|
||||||
|
void Model01Side::sendLEDBank(byte bank) {
|
||||||
|
uint8_t data[LED_BYTES_PER_BANK + 1];
|
||||||
|
data[0] = TWI_CMD_LED_BASE + bank;
|
||||||
|
for (uint8_t i = 0 ; i < LED_BYTES_PER_BANK; i++) {
|
||||||
|
/* While the ATTiny controller does have a global brightness command, it is
|
||||||
|
* limited to 32 levels, and those aren't nicely spread out either. For this
|
||||||
|
* reason, we're doing our own brightness adjustment on this side, because
|
||||||
|
* that results in a considerably smoother curve. */
|
||||||
|
uint8_t c = ledData.bytes[bank][i];
|
||||||
|
if (c > brightness_adjustment_)
|
||||||
|
c -= brightness_adjustment_;
|
||||||
|
else
|
||||||
|
c = 0;
|
||||||
|
|
||||||
|
data[i + 1] = pgm_read_byte(&gamma8[c]);
|
||||||
|
}
|
||||||
|
uint8_t result = twi_writeTo(addr, data, ELEMENTS(data), 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model01Side::setAllLEDsTo(cRGB color) {
|
||||||
|
uint8_t data[] = {TWI_CMD_LED_SET_ALL_TO,
|
||||||
|
pgm_read_byte(&gamma8[color.b]),
|
||||||
|
pgm_read_byte(&gamma8[color.g]),
|
||||||
|
pgm_read_byte(&gamma8[color.r])
|
||||||
|
};
|
||||||
|
uint8_t result = twi_writeTo(addr, data, ELEMENTS(data), 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model01Side::setOneLEDTo(byte led, cRGB color) {
|
||||||
|
uint8_t data[] = {TWI_CMD_LED_SET_ONE_TO,
|
||||||
|
led,
|
||||||
|
pgm_read_byte(&gamma8[color.b]),
|
||||||
|
pgm_read_byte(&gamma8[color.g]),
|
||||||
|
pgm_read_byte(&gamma8[color.r])
|
||||||
|
};
|
||||||
|
uint8_t result = twi_writeTo(addr, data, ELEMENTS(data), 1, 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace keyboardio
|
||||||
|
} // namespace driver
|
||||||
|
} // namespace kaleidoscope
|
||||||
|
|
||||||
|
#endif // ifndef KALEIDOSCOPE_VIRTUAL_BUILD
|
@ -0,0 +1,106 @@
|
|||||||
|
// -*- mode: c++ -*-
|
||||||
|
/* kaleidoscope::driver::keyboardio::Model01Side
|
||||||
|
* Copyright (C) 2015-2020 Keyboard.io, Inc
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace kaleidoscope {
|
||||||
|
namespace driver {
|
||||||
|
namespace keyboardio {
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "wire-protocol-constants.h"
|
||||||
|
|
||||||
|
// We allow cRGB/CRGB to be defined already when this is included.
|
||||||
|
//
|
||||||
|
#ifndef CRGB
|
||||||
|
struct cRGB {
|
||||||
|
uint8_t b;
|
||||||
|
uint8_t g;
|
||||||
|
uint8_t r;
|
||||||
|
};
|
||||||
|
#define CRGB(r,g,b) (cRGB){b, g, r}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LED_BANKS 4
|
||||||
|
|
||||||
|
#define LEDS_PER_HAND 32
|
||||||
|
#define LED_BYTES_PER_BANK sizeof(cRGB) * LEDS_PER_HAND/LED_BANKS
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
cRGB leds[LEDS_PER_HAND];
|
||||||
|
byte bytes[LED_BANKS][LED_BYTES_PER_BANK];
|
||||||
|
} LEDData_t;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
uint8_t rows[4];
|
||||||
|
uint32_t all;
|
||||||
|
} keydata_t;
|
||||||
|
|
||||||
|
// config options
|
||||||
|
|
||||||
|
#ifndef KALEIDOSCOPE_VIRTUAL_BUILD
|
||||||
|
// used to configure interrupts, configuration for a particular controller
|
||||||
|
class Model01Side {
|
||||||
|
public:
|
||||||
|
explicit Model01Side(byte setAd01);
|
||||||
|
~Model01Side() {}
|
||||||
|
|
||||||
|
int readVersion();
|
||||||
|
|
||||||
|
byte setKeyscanInterval(byte delay);
|
||||||
|
int readKeyscanInterval();
|
||||||
|
|
||||||
|
byte setLEDSPIFrequency(byte frequency);
|
||||||
|
int readLEDSPIFrequency();
|
||||||
|
|
||||||
|
void sendLEDData();
|
||||||
|
void setOneLEDTo(byte led, cRGB color);
|
||||||
|
void setAllLEDsTo(cRGB color);
|
||||||
|
keydata_t getKeyData();
|
||||||
|
bool readKeys();
|
||||||
|
LEDData_t ledData;
|
||||||
|
uint8_t controllerAddress();
|
||||||
|
|
||||||
|
void setBrightness(uint8_t brightness) {
|
||||||
|
brightness_adjustment_ = 255 - brightness;
|
||||||
|
}
|
||||||
|
uint8_t getBrightness() {
|
||||||
|
return 255 - brightness_adjustment_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t brightness_adjustment_ = 0;
|
||||||
|
int addr;
|
||||||
|
int ad01;
|
||||||
|
keydata_t keyData;
|
||||||
|
byte nextLEDBank = 0;
|
||||||
|
void sendLEDBank(byte bank);
|
||||||
|
int readRegister(uint8_t cmd);
|
||||||
|
};
|
||||||
|
#else // ifndef KALEIDOSCOPE_VIRTUAL_BUILD
|
||||||
|
class Model01Side;
|
||||||
|
#endif // ifndef KALEIDOSCOPE_VIRTUAL_BUILD
|
||||||
|
|
||||||
|
} // namespace keyboardio
|
||||||
|
} // namespace driver
|
||||||
|
} // namespace kaleidoscope
|
@ -0,0 +1,51 @@
|
|||||||
|
/* KeyboardioScanner
|
||||||
|
* Copyright (C) 2015-2018 Keyboard.io, Inc
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define TWI_CMD_NONE 0x00
|
||||||
|
#define TWI_CMD_VERSION 0x01
|
||||||
|
#define TWI_CMD_KEYSCAN_INTERVAL 0x02
|
||||||
|
#define TWI_CMD_LED_SET_ALL_TO 0x03
|
||||||
|
#define TWI_CMD_LED_SET_ONE_TO 0x04
|
||||||
|
#define TWI_CMD_COLS_USE_PULLUPS 0x05
|
||||||
|
#define TWI_CMD_LED_SPI_FREQUENCY 0x06
|
||||||
|
|
||||||
|
#define LED_SPI_FREQUENCY_4MHZ 0x07
|
||||||
|
#define LED_SPI_FREQUENCY_2MHZ 0x06
|
||||||
|
#define LED_SPI_FREQUENCY_1MHZ 0x05
|
||||||
|
#define LED_SPI_FREQUENCY_512KHZ 0x04
|
||||||
|
#define LED_SPI_FREQUENCY_256KHZ 0x03
|
||||||
|
#define LED_SPI_FREQUENCY_128KHZ 0x02
|
||||||
|
#define LED_SPI_FREQUENCY_64KHZ 0x01
|
||||||
|
#define LED_SPI_OFF 0x00
|
||||||
|
|
||||||
|
|
||||||
|
// 512KHZ seems to be the sweet spot in early testing
|
||||||
|
// so make it the default
|
||||||
|
#define LED_SPI_FREQUENCY_DEFAULT LED_SPI_FREQUENCY_512KHZ
|
||||||
|
|
||||||
|
|
||||||
|
#define TWI_CMD_LED_BASE 0x80
|
||||||
|
|
||||||
|
#define TWI_REPLY_NONE 0x00
|
||||||
|
#define TWI_REPLY_KEYDATA 0x01
|
Loading…
Reference in new issue