Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CharShift: Configuration plugin #1069

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,27 @@ namespace plugin {

// =============================================================================
// CharShift class variables
CharShift::KeyPair const * CharShift::progmem_keypairs_{nullptr};
uint8_t CharShift::num_keypairs_{0};

charshift::Storage * CharShift::storage_;
bool CharShift::reverse_shift_state_{false};

static auto progmem_storage_ = charshift::ProgmemStorage();

// =============================================================================
// Event handlers

// -----------------------------------------------------------------------------
EventHandlerResult CharShift::onSetup() {
if (!storage_) {
storage_ = &progmem_storage_;
}
return EventHandlerResult::OK;
}
EventHandlerResult CharShift::onNameQuery() {
return ::Focus.sendName(F("CharShift"));
}
EventHandlerResult CharShift::onFocusEvent(const char *command) {
return storage_->onFocusEvent(command);
}

// -----------------------------------------------------------------------------
EventHandlerResult CharShift::onKeyEvent(KeyEvent &event) {
Expand Down Expand Up @@ -117,32 +125,12 @@ bool CharShift::isCharShiftKey(Key key) {

CharShift::KeyPair CharShift::decodeCharShiftKey(Key key) {
uint8_t i = key.getRaw() - ranges::CS_FIRST;
if (i < numKeyPairs()) {
return readKeyPair(i);
if (i < storage_->numKeyPairs()) {
return storage_->readKeyPair(i);
}
return {Key_NoKey, Key_NoKey};
}

// This should be overridden if the KeyPairs array is stored in EEPROM
__attribute__((weak))
uint8_t CharShift::numKeyPairs() {
return numProgmemKeyPairs();
}

// This should be overridden if the KeyPairs array is stored in EEPROM
__attribute__((weak))
CharShift::KeyPair CharShift::readKeyPair(uint8_t n) {
return readKeyPairFromProgmem(n);
}

uint8_t CharShift::numProgmemKeyPairs() {
return num_keypairs_;
}

CharShift::KeyPair CharShift::readKeyPairFromProgmem(uint8_t n) {
return cloneFromProgmem(progmem_keypairs_[n]);
}

} // namespace plugin
} // namespace kaleidoscope

Expand Down
96 changes: 66 additions & 30 deletions plugins/Kaleidoscope-CharShift/src/kaleidoscope/plugin/CharShift.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
namespace kaleidoscope {
namespace plugin {

namespace charshift {
class Storage;
}

// =============================================================================
/// Kaleidoscope plugin for independently assigning shifted symbols
///
Expand All @@ -36,9 +40,11 @@ namespace plugin {
class CharShift : public Plugin {

public:
EventHandlerResult onSetup();
EventHandlerResult onNameQuery();
EventHandlerResult onKeyEvent(KeyEvent &event);
EventHandlerResult beforeReportingState(const KeyEvent &event);
EventHandlerResult onFocusEvent(const char *command);

// ---------------------------------------------------------------------------
/// A structure that stores CharShift key pair values
Expand All @@ -63,24 +69,15 @@ class CharShift : public Plugin {
KeyPair() = default;
};

/// Configure the KeyPairs array in PROGMEM
///
/// This function configures the PROGMEM array of `KeyPair` objects,
/// automatically setting the internal count variable from the size of the
/// `keypairs` array given, which must be a fixed-sized array, not a pointer.
/// Generally, it will be called via the `KEYPAIRS()` preprocessor macro, not
/// directly by user code.
template <uint8_t _num_keypairs>
static void setProgmemKeyPairs(KeyPair const(&keypairs)[_num_keypairs]) {
progmem_keypairs_ = keypairs;
num_keypairs_ = _num_keypairs;
charshift::Storage &storage() {
return *storage_;
}
void setStorage(charshift::Storage *st) {
storage_ = st;
}

private:
// A pointer to an array of `KeyPair` objects in PROGMEM
static KeyPair const * progmem_keypairs_;
// The size of the PROGMEM array of `KeyPair` objects
static uint8_t num_keypairs_;
static charshift::Storage *storage_;

// If a `shift` key needs to be suppressed in `beforeReportingState()`
static bool reverse_shift_state_;
Expand All @@ -90,25 +87,64 @@ class CharShift : public Plugin {

/// Look up the `KeyPair` specified by the given keymap entry
static KeyPair decodeCharShiftKey(Key key);
};

/// Get the total number of KeyPairs defined
///
/// This function can be overridden in order to store the `KeyPair` array in
/// EEPROM instead of PROGMEM.
static uint8_t numKeyPairs();
namespace charshift {

class Storage {
public:
Storage() {}

static uint8_t numKeyPairs() {
return num_keypairs_;
}
static CharShift::KeyPair readKeyPair(uint8_t n) {
return CharShift::KeyPair(Key_NoKey, Key_NoKey);
}

EventHandlerResult onFocusEvent(const char *command) {
return EventHandlerResult::OK;
}

protected:
static uint8_t num_keypairs_;
};

class ProgmemStorage: public Storage {
public:

static CharShift::KeyPair readKeyPair(uint8_t n);

/// Get the `KeyPair` at the specified index from the defined `KeyPair` array
/// Configure the KeyPairs array in PROGMEM
///
/// This function can be overridden in order to store the `KeyPair` array in
/// EEPROM instead of PROGMEM.
static KeyPair readKeyPair(uint8_t n);

// Default for `keypairsCount()`: size of the PROGMEM array
static uint8_t numProgmemKeyPairs();
// Default for `readKeypair(i)`: fetch the value from PROGMEM
static KeyPair readKeyPairFromProgmem(uint8_t n);
/// This function configures the PROGMEM array of `KeyPair` objects,
/// automatically setting the internal count variable from the size of the
/// `keypairs` array given, which must be a fixed-sized array, not a pointer.
/// Generally, it will be called via the `KEYPAIRS()` preprocessor macro, not
/// directly by user code.
template <uint8_t _num_keypairs>
static void setKeyPairs(CharShift::KeyPair const(&keypairs)[_num_keypairs]) {
keypairs_ = keypairs;
num_keypairs_ = _num_keypairs;
}

private:
// A pointer to an array of `KeyPair` objects in PROGMEM
static CharShift::KeyPair const *keypairs_;
};

class EEPROMStorage: public Storage {
public:
void setup(uint8_t num_pairs);
static CharShift::KeyPair readKeyPair(uint8_t n);

EventHandlerResult onFocusEvent(const char *command);
private:
static uint16_t storage_base_;
};

}

} // namespace plugin
} // namespace kaleidoscope

Expand All @@ -124,7 +160,7 @@ extern kaleidoscope::plugin::CharShift CharShift;
static kaleidoscope::plugin::CharShift::KeyPair const kp_table[] PROGMEM = { \
keypairs \
}; \
CharShift.setProgmemKeyPairs(kp_table); \
CharShift.storage().setKeyPairs(kp_table); \
}

/// Define an `KeyPair` entry in a keymap
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/* -*- mode: c++ -*-
* Kaleidoscope-CharShift -- Independently assign shifted and unshifted symbols
* Copyright (C) 2021 Keyboard.io, Inc
*
* 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, version 3.
*
* 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 "kaleidoscope/plugin/CharShift.h"

#include <Kaleidoscope-Ranges.h>
#include <Kaleidoscope-FocusSerial.h>
#include <Kaleidoscope-EEPROM-Settings.h>

#include "kaleidoscope/KeyAddr.h"
#include "kaleidoscope/key_defs.h"
#include "kaleidoscope/KeyEvent.h"
#include "kaleidoscope/keyswitch_state.h"
#include "kaleidoscope/progmem_helpers.h"
#include "kaleidoscope/Runtime.h"

namespace kaleidoscope {
namespace plugin {
namespace charshift {

// =============================================================================
// Storage class variables

uint8_t Storage::num_keypairs_;

CharShift::KeyPair const * ProgmemStorage::keypairs_{nullptr};

uint16_t EEPROMStorage::storage_base_;


// =============================================================================
// Progmem Storage

CharShift::KeyPair ProgmemStorage::readKeyPair(uint8_t n) {
return cloneFromProgmem(keypairs_[n]);
}


// =============================================================================
// EEPROM Storage
EventHandlerResult EEPROMStorage::onFocusEvent(const char *command) {
if (::Focus.handleHelp(command, PSTR("charshift.map")))
return EventHandlerResult::OK;

if (strcmp_P(command, PSTR("charshift.map")) != 0)
return EventHandlerResult::OK;

if (::Focus.isEOL()) {
// We dump key by key, rather than pairs, because the end result is the
// same, and dumping one by one is less code.
for (uint16_t i = 0; i < num_keypairs_ * 2; i += 2) {
Key k;

Runtime.storage().get(storage_base_ + i, k);
::Focus.send(k);
}
} else {
uint16_t pos = 0;

// We read one key at a time, rather than a keypair, to better handle
// partials and failure, and to make the code simpler.
while (!::Focus.isEOL()) {
Key k;

::Focus.read(k);
Runtime.storage().put(storage_base_ + pos, k);
pos += 2;
}
Runtime.storage().commit();
}

return EventHandlerResult::EVENT_CONSUMED;
}

void EEPROMStorage::setup(uint8_t num_keypairs) {
num_keypairs_ = num_keypairs;

storage_base_ = ::EEPROMSettings.requestSlice(num_keypairs * 4);
}

CharShift::KeyPair EEPROMStorage::readKeyPair(uint8_t n) {
uint16_t pos = storage_base_ + n * 4; // 4: Size of a keypair.
uint16_t raw_lower = Runtime.storage().read(pos);
uint16_t raw_upper = Runtime.storage().read(pos + 2);

return CharShift::KeyPair(Key(raw_lower), Key(raw_upper));
}

}


} // namespace plugin
} // namespace kaleidoscope