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