diff --git a/examples/Devices/Keyboardio/Model100/Model100.ino b/examples/Devices/Keyboardio/Model100/Model100.ino
index 8eb85b8b..70e37798 100644
--- a/examples/Devices/Keyboardio/Model100/Model100.ino
+++ b/examples/Devices/Keyboardio/Model100/Model100.ino
@@ -21,7 +21,7 @@
#include "Kaleidoscope-EEPROM-Keymap.h"
// Support for communicating with the host via a simple Serial protocol
-#include "Kaleidoscope-FocusSerial.h"
+//#include "Kaleidoscope-FocusSerial.h"
// Support for keys that move the mouse
#include "Kaleidoscope-MouseKeys.h"
@@ -430,16 +430,16 @@ KALEIDOSCOPE_INIT_PLUGINS(
// Focus allows bi-directional communication with the host, and is the
// interface through which the keymap in EEPROM can be edited.
- Focus,
+ //Focus,
// FocusSettingsCommand adds a few Focus commands, intended to aid in
// changing some settings of the keyboard, such as the default layer (via the
// `settings.defaultLayer` command)
- FocusSettingsCommand,
+ //FocusSettingsCommand,
// FocusEEPROMCommand adds a set of Focus commands, which are very helpful in
// both debugging, and in backing up one's EEPROM contents.
- FocusEEPROMCommand,
+// FocusEEPROMCommand,
// The boot greeting effect pulses the LED button for 10 seconds after the
// keyboard is first connected
@@ -530,8 +530,8 @@ void setup() {
// We set the brightness of the rainbow effects to 150 (on a scale of 0-255)
// This draws more than 500mA, but looks much nicer than a dimmer effect
- LEDRainbowEffect.brightness(150);
- LEDRainbowWaveEffect.brightness(150);
+ LEDRainbowEffect.brightness(255);
+ LEDRainbowWaveEffect.brightness(255);
// Set the action key the test mode should listen for to Left Fn
HardwareTestMode.setActionKey(R3C6);
@@ -551,12 +551,12 @@ void setup() {
// one wants to use these layers, just set the default layer to one in EEPROM,
// by using the `settings.defaultLayer` Focus command, or by using the
// `keymap.onlyCustom` command to use EEPROM layers only.
- EEPROMKeymap.setup(5);
+ //EEPROMKeymap.setup(5);
// We need to tell the Colormap plugin how many layers we want to have custom
// maps for. To make things simple, we set it to five layers, which is how
// many editable layers we have (see above).
- ColormapEffect.max_layers(5);
+ //ColormapEffect.max_layers(5);
}
/** loop is the second of the standard Arduino sketch functions.
diff --git a/plugins/Kaleidoscope-Hardware-Keyboardio-Model100/src/kaleidoscope/device/keyboardio/Model100.cpp b/plugins/Kaleidoscope-Hardware-Keyboardio-Model100/src/kaleidoscope/device/keyboardio/Model100.cpp
index 9ccb38d9..e4c5db78 100644
--- a/plugins/Kaleidoscope-Hardware-Keyboardio-Model100/src/kaleidoscope/device/keyboardio/Model100.cpp
+++ b/plugins/Kaleidoscope-Hardware-Keyboardio-Model100/src/kaleidoscope/device/keyboardio/Model100.cpp
@@ -15,16 +15,16 @@
* this program. If not, see .
*/
-#ifdef ARDUINO_GD32_keyboardio_model_100
+#ifdef ARDUINO_keyboardio_model_100
#include "Arduino.h" // for PROGMEM
#include "kaleidoscope/device/keyboardio/Model100.h" // for Model100LEDDriver...
#include "kaleidoscope/key_events.h"
#include "kaleidoscope/driver/keyscanner/Base_Impl.h"
+#include "Wire.h"
+
#ifndef KALEIDOSCOPE_VIRTUAL_BUILD
-#include
-#include
#endif // ifndef KALEIDOSCOPE_VIRTUAL_BUILD
namespace kaleidoscope {
@@ -48,14 +48,13 @@ driver::keyboardio::Model100Side Model100Hands::leftHand(0);
driver::keyboardio::Model100Side Model100Hands::rightHand(3);
void Model100Hands::setup(void) {
- // This lets the keyboard pull up to 1.6 amps from the host.
- // That violates the USB spec. But it sure is pretty looking
- DDRE |= _BV(6);
- PORTE &= ~_BV(6);
+ delay(100);
+ pinMode(PB9, OUTPUT_OPEN_DRAIN);
+ digitalWrite(PB9, LOW);
+ delay(105); // TODO remove this when we remove it from the attiny code
+ Wire.begin();
+ Wire.setClock(400000);
- // Set B4, the overcurrent check to an input with an internal pull-up
- DDRB &= ~_BV(4); // set bit, input
- PORTB &= ~_BV(4); // set bit, enable pull-up resistor
}
/********* LED Driver *********/
@@ -103,7 +102,6 @@ cRGB Model100LEDDriver::getCrgbAt(uint8_t i) {
void Model100LEDDriver::syncLeds() {
if (!isLEDChanged)
return;
-
// LED Data is stored in four "banks" for each side
// We send it all at once to make it look nicer.
// We alternate left and right hands because otherwise
@@ -125,10 +123,6 @@ void Model100LEDDriver::syncLeds() {
isLEDChanged = false;
}
-boolean Model100LEDDriver::ledPowerFault() {
- // TODO remove - obsolete
-}
-
/********* Key scanner *********/
driver::keyboardio::keydata_t Model100KeyScanner::leftHandState;
@@ -137,16 +131,26 @@ driver::keyboardio::keydata_t Model100KeyScanner::previousLeftHandState;
driver::keyboardio::keydata_t Model100KeyScanner::previousRightHandState;
void Model100KeyScanner::enableScannerPower(void) {
+// Turn on the switched 5V network.
+// make sure this happens at least 100ms after USB connect
+// to satisfy inrush limits
+ //
+ pinMode(PB9, OUTPUT_OPEN_DRAIN);
+ digitalWrite(PB9, LOW);
+}
+
+void Model100KeyScanner::disableScannerPower(void) {
// Turn on power to the 5V net
//
- pinMode(PC13, OUTPUT_OPEN_DRAIN);
- digitalWrite(PC13, LOW);
+ pinMode(PB9, OUTPUT_OPEN_DRAIN);
+ digitalWrite(PB9, HIGH);
}
+
+
void Model100KeyScanner::setup() {
- wdt_disable();
- delay(100);
enableScannerPower();
+ delay(250);
}
void Model100KeyScanner::readMatrix() {
@@ -228,6 +232,7 @@ uint8_t Model100KeyScanner::previousPressedKeyswitchCount() {
/********* Hardware plugin *********/
void Model100::setup() {
+ Model100KeyScanner::setup();
Model100Hands::setup();
kaleidoscope::device::Base::setup();
}
diff --git a/plugins/Kaleidoscope-Hardware-Keyboardio-Model100/src/kaleidoscope/device/keyboardio/Model100.h b/plugins/Kaleidoscope-Hardware-Keyboardio-Model100/src/kaleidoscope/device/keyboardio/Model100.h
index 606f3e93..817f53cd 100644
--- a/plugins/Kaleidoscope-Hardware-Keyboardio-Model100/src/kaleidoscope/device/keyboardio/Model100.h
+++ b/plugins/Kaleidoscope-Hardware-Keyboardio-Model100/src/kaleidoscope/device/keyboardio/Model100.h
@@ -17,7 +17,11 @@
#pragma once
-#ifdef ARDUINO_GD32_keyboardio_model_100
+#ifdef ARDUINO_keyboardio_model_100
+
+#ifndef EEPROM_EMULATION_SIZE
+#define EEPROM_EMULATION_SIZE 4096
+#endif
#include
@@ -29,17 +33,24 @@ struct cRGB {
uint8_t r;
};
-#include "kaleidoscope/device/ATmega32U4Keyboard.h"
#include "kaleidoscope/driver/keyscanner/Base.h"
+#include "kaleidoscope/driver/storage/GD32Flash.h"
#include "kaleidoscope/driver/keyboardio/Model100Side.h"
#include "kaleidoscope/driver/led/Base.h"
+#include "kaleidoscope/device/Base.h"
+#include "kaleidoscope/driver/hid/Keyboardio.h"
#include "kaleidoscope/driver/bootloader/gd32/Base.h"
namespace kaleidoscope {
namespace device {
namespace keyboardio {
+struct Model100StorageProps: public kaleidoscope::driver::storage::GD32FlashProps {
+ static constexpr uint16_t length = EEPROM_EMULATION_SIZE;
+};
+
+
struct Model100LEDDriverProps : public kaleidoscope::driver::led::BaseProps {
static constexpr uint8_t led_count = 64;
static constexpr uint8_t key_led_map[] PROGMEM = {
@@ -60,7 +71,6 @@ class Model100LEDDriver : public kaleidoscope::driver::led::Base HID;
+
typedef Model100LEDDriverProps LEDDriverProps;
typedef Model100LEDDriver LEDDriver;
typedef Model100KeyScannerProps KeyScannerProps;
typedef Model100KeyScanner KeyScanner;
+ typedef Model100StorageProps StorageProps;
+ typedef kaleidoscope::driver::storage::GD32Flash Storage;
+
typedef kaleidoscope::driver::bootloader::gd32::Base BootLoader;
static constexpr const char *short_name = "kbio100";
};
diff --git a/plugins/Kaleidoscope-Hardware-Keyboardio-Model100/src/kaleidoscope/driver/keyboardio/Model100Side.cpp b/plugins/Kaleidoscope-Hardware-Keyboardio-Model100/src/kaleidoscope/driver/keyboardio/Model100Side.cpp
index 8d4c6e31..11a48eb6 100644
--- a/plugins/Kaleidoscope-Hardware-Keyboardio-Model100/src/kaleidoscope/driver/keyboardio/Model100Side.cpp
+++ b/plugins/Kaleidoscope-Hardware-Keyboardio-Model100/src/kaleidoscope/driver/keyboardio/Model100Side.cpp
@@ -24,10 +24,8 @@
#include
#include "Model100Side.h"
-
-extern "C" {
-#include "kaleidoscope/device/keyboardio/twi.h"
-}
+#include
+#include
#include "kaleidoscope/driver/color/GammaCorrection.h"
@@ -43,9 +41,7 @@ uint8_t twi_uninitialized = 1;
Model100Side::Model100Side(byte setAd01) {
ad01 = setAd01;
addr = SCANNER_I2C_ADDR_BASE | ad01;
- if (twi_uninitialized--) {
- twi_init();
- }
+ markDeviceUnavailable();
}
// Returns the relative controller addresss. The expected range is 0-3
@@ -72,8 +68,7 @@ uint8_t Model100Side::controllerAddress() {
// https://www.arduino.cc/en/Reference/WireEndTransmission
byte Model100Side::setKeyscanInterval(byte delay) {
uint8_t data[] = {TWI_CMD_KEYSCAN_INTERVAL, delay};
- uint8_t result = twi_writeTo(addr, data, ELEMENTS(data), 1, 0);
-
+ uint8_t result = writeData(data, ELEMENTS(data));
return result;
}
@@ -103,34 +98,84 @@ int Model100Side::readLEDSPIFrequency() {
// https://www.arduino.cc/en/Reference/WireEndTransmission
byte Model100Side::setLEDSPIFrequency(byte frequency) {
uint8_t data[] = {TWI_CMD_LED_SPI_FREQUENCY, frequency};
- uint8_t result = twi_writeTo(addr, data, ELEMENTS(data), 1, 0);
+ uint8_t result = writeData(data, ELEMENTS(data));
return result;
}
+// GD32 I2C implements timeouts which will cause a stall when a device does not answer.
+// This method will verify that the device is around and ready to talk.
+bool Model100Side::isDeviceAvailable() {
+ return true;
+ // if the counter is zero, that's the special value that means "we know it's there"
+ if (unavailable_device_check_countdown_ == 0) {
+ return true;
+ }
-int Model100Side::readRegister(uint8_t cmd) {
+ // if the time to check counter is 1, check for the device
+
+ else if (--unavailable_device_check_countdown_ == 0) {
+ uint8_t wire_result;
+ Wire.beginTransmission(addr);
+ wire_result = Wire.endTransmission();
+ //if the check succeeds
+ if (wire_result == 0) {
+ // unavailable_device_check_countdown_ = 0; // TODO this is already true
+ return true;
+ } else {
+ // set the time to check counter to max
+ unavailable_device_check_countdown_ = UNAVAILABLE_DEVICE_COUNTDOWN_MAX;
+ return false;
+ }
+ } else {
+ // we've decremented the counter, but it's not time to probe for the device yet.
+ return false;
+ }
- byte return_value = 0;
+}
- uint8_t data[] = {cmd};
- uint8_t result = twi_writeTo(addr, data, ELEMENTS(data), 1, 0);
+void Model100Side::markDeviceUnavailable() {
+ unavailable_device_check_countdown_ = 1; // We think there was a comms problem. Check on the next cycle
+}
+uint8_t Model100Side::writeData(uint8_t *data, uint8_t length) {
+ if (isDeviceAvailable() == false) {
+ return 1;
+ }
+ Wire.beginTransmission(addr);
+ Wire.write(data, length);
+ uint8_t result = Wire.endTransmission();
+ if (result) {
+ markDeviceUnavailable();
+ }
+ return result;
+}
+
+int Model100Side::readRegister(uint8_t cmd) {
+ byte return_value = 0;
+ uint8_t data[] = {cmd};
+ uint8_t result = writeData(data, ELEMENTS(data));
+ // If the setup failed, return. This means there was a problem asking for the register
+ if (result) {
+ return -1;
+ }
- delayMicroseconds(15); // We may be able to drop this in the future
+ delayMicroseconds(50); // TODO 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];
+ uint8_t rxBuffer[1] = {0};
// perform blocking read into buffer
- uint8_t read = twi_readFrom(addr, rxBuffer, ELEMENTS(rxBuffer), true);
- if (read > 0) {
- return rxBuffer[0];
+
+ Wire.requestFrom(addr, 1); // request 1 byte from the keyscanner
+ if (Wire.available()) {
+ return Wire.read();
} else {
+ markDeviceUnavailable();
return -1;
}
@@ -139,20 +184,28 @@ int Model100Side::readRegister(uint8_t cmd) {
// gives information on the key that was just pressed or released.
bool Model100Side::readKeys() {
+ if (isDeviceAvailable() == false) {
+ return false;
+ }
- uint8_t rxBuffer[5];
-
+ uint8_t row_counter = 0;
// 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 {
+ uint8_t read = 0;
+ uint8_t bytes_returned = 0;
+ bytes_returned = Wire.requestFrom(addr, 5); // request 5 bytes from the keyscanner
+ if (bytes_returned < 5) {
return false;
}
+ if (Wire.available()) {
+ read = Wire.read();
+ if (TWI_REPLY_KEYDATA == read) {
+ while (Wire.available()) {
+ keyData.rows[row_counter++] = Wire.read();
+ }
+ return true;
+ }
+ }
+ return false;
}
keydata_t Model100Side::getKeyData() {
@@ -184,7 +237,7 @@ void Model100Side::sendLEDBank(byte bank) {
data[i + 1] = pgm_read_byte(&gamma8[c]);
}
- uint8_t result = twi_writeTo(addr, data, ELEMENTS(data), 1, 0);
+ uint8_t result = writeData(data, ELEMENTS(data));
}
void Model100Side::setAllLEDsTo(cRGB color) {
@@ -193,7 +246,7 @@ void Model100Side::setAllLEDsTo(cRGB color) {
pgm_read_byte(&gamma8[color.g]),
pgm_read_byte(&gamma8[color.r])
};
- uint8_t result = twi_writeTo(addr, data, ELEMENTS(data), 1, 0);
+ uint8_t result = writeData(data, ELEMENTS(data));
}
void Model100Side::setOneLEDTo(byte led, cRGB color) {
@@ -203,7 +256,7 @@ void Model100Side::setOneLEDTo(byte led, cRGB color) {
pgm_read_byte(&gamma8[color.g]),
pgm_read_byte(&gamma8[color.r])
};
- uint8_t result = twi_writeTo(addr, data, ELEMENTS(data), 1, 0);
+ uint8_t result = writeData(data, ELEMENTS(data));
}
diff --git a/plugins/Kaleidoscope-Hardware-Keyboardio-Model100/src/kaleidoscope/driver/keyboardio/Model100Side.h b/plugins/Kaleidoscope-Hardware-Keyboardio-Model100/src/kaleidoscope/driver/keyboardio/Model100Side.h
index 1841095b..2d7838e4 100644
--- a/plugins/Kaleidoscope-Hardware-Keyboardio-Model100/src/kaleidoscope/driver/keyboardio/Model100Side.h
+++ b/plugins/Kaleidoscope-Hardware-Keyboardio-Model100/src/kaleidoscope/driver/keyboardio/Model100Side.h
@@ -78,9 +78,12 @@ class Model100Side {
void setAllLEDsTo(cRGB color);
keydata_t getKeyData();
bool readKeys();
+
LEDData_t ledData;
- uint8_t controllerAddress();
+ uint8_t controllerAddress();
+ bool isDeviceAvailable();
+ void markDeviceUnavailable();
void setBrightness(uint8_t brightness) {
brightness_adjustment_ = 255 - brightness;
}
@@ -93,9 +96,14 @@ class Model100Side {
int addr;
int ad01;
keydata_t keyData;
+ // a value of 0 is "device seen" - anything else is how many cycles before we should
+ // check for the device
+ uint16_t unavailable_device_check_countdown_ = 0;
+ static const uint16_t UNAVAILABLE_DEVICE_COUNTDOWN_MAX = 0x00FFU;
byte nextLEDBank = 0;
void sendLEDBank(byte bank);
int readRegister(uint8_t cmd);
+ uint8_t writeData(uint8_t* data, uint8_t length);
};
#else // ifndef KALEIDOSCOPE_VIRTUAL_BUILD
class Model100Side;