Git Product home page Git Product logo

kaleidoscope's People

Contributors

algernon avatar aspiers avatar bjc avatar cdisselkoen avatar evybongers avatar gedankenexperimenter avatar hkmix avatar iliana avatar indirect avatar jamadagni avatar jamesnvc avatar jennigma avatar kingparra avatar martinakcsilla avatar mattvenn avatar maxg87 avatar nicohood avatar ninjaaron avatar noerw avatar nospam2000 avatar numist avatar obra avatar rom1detroyes avatar sjb avatar tiltowait avatar tlyu avatar toykeeper avatar tremby avatar wez avatar wildlymanifest avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kaleidoscope's Issues

Key layouts here is not what was shipped

When I overwrote the Micro for the first time testing, my keys changed. I thought I had royally screwed up the Micro's program.

I'm also looking to get back the start/stop keys.

Thanks guys!

NOTICE and LICENSE mismatch (simple fix)

I noticed that the LICENSE file now says GPLv2, which seems fine.

But the NOTICE file still mentions that the Keyboard.IO driver is licensed under the Apache 2.0.

I’d suggest you update the NOTICE file to point to the right license.

Since NOTICE file is not needed under GPL (but is needed if you contribute to an Apache Foundation project), it might even make sense to change the NOTICE file to README or README.markdown. Feel free to keep the filename as it is, if that suits your style better. Not a biggie there 😸

Add indentation-off guards to examples

make astyle is great, but it reformats the KEYMAP and KEYMAP_STACKED macros too in the examples. Those should be guarded with hints that stop astyle from doing so.

See here

Verifying sketch fails with example firmware

After following the instructions listed here to install the Arduino IDE and set up the Kaleidoscope firmware, I get two errors when building my sketch (The sketch is currently a copy of the example firmware at https://github.com/keyboardio/Model01-Firmware).

The first error complains about their being two HID.h libraries, one in the arduino install directory and one in the keyboardio library. I tried moving the arduino one out of the way, but the second error stayed.

The second error indicates that it can't find the definition for various mouse-related things when compiling the MouseKeys plugin.

Full error message below:

Archiving built core (caching) in: /tmp/arduino_cache_613584/core/core_keyboardio_avr_model01_3f7379d53668113d472969c15c3bd10d.a Multiple libraries were found for "HID.h" Used: /home/james/software/arduino-1.8.3/hardware/arduino/avr/libraries/HID Not used: /home/james/Arduino/hardware/keyboardio/avr/libraries/Arduino-HID libraries/Kaleidoscope-MouseKeys/Kaleidoscope-MouseKeys.a(Kaleidoscope-MouseKeys.cpp.o): In function `MouseKeys_::scrollWheel(unsigned char)': /home/james/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope-MouseKeys/src/Kaleidoscope-MouseKeys.cpp:110: undefined reference to `Mouse' /home/james/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope-MouseKeys/src/Kaleidoscope-MouseKeys.cpp:110: undefined reference to `Mouse' /home/james/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope-MouseKeys/src/Kaleidoscope-MouseKeys.cpp:110: undefined reference to `Mouse_::move(signed char, signed char, signed char)' libraries/Kaleidoscope-MouseKeys/Kaleidoscope-MouseKeys.a(MouseWrapper.cpp.o): In function `MouseWrapper_::MouseWrapper_()': /home/james/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope-MouseKeys/src/MouseWrapper.cpp:44: undefined reference to `Mouse' /home/james/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope-MouseKeys/src/MouseWrapper.cpp:44: undefined reference to `Mouse' /home/james/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope-MouseKeys/src/MouseWrapper.cpp:44: undefined reference to `Mouse_::begin()' /home/james/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope-MouseKeys/src/MouseWrapper.cpp:44: undefined reference to `AbsoluteMouse' /home/james/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope-MouseKeys/src/MouseWrapper.cpp:44: undefined reference to `AbsoluteMouse' /home/james/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope-MouseKeys/src/MouseWrapper.cpp:44: undefined reference to `AbsoluteMouse_::begin()' libraries/Kaleidoscope-MouseKeys/Kaleidoscope-MouseKeys.a(MouseWrapper.cpp.o): In function `MouseWrapper_::press_button(unsigned char)': /home/james/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope-MouseKeys/src/MouseWrapper.cpp:44: undefined reference to `Mouse' /home/james/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope-MouseKeys/src/MouseWrapper.cpp:44: undefined reference to `Mouse' /home/james/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope-MouseKeys/src/MouseWrapper.cpp:44: undefined reference to `Mouse_::press(unsigned char)' libraries/Kaleidoscope-MouseKeys/Kaleidoscope-MouseKeys.a(MouseWrapper.cpp.o): In function `MouseWrapper_::release_button(unsigned char)': /home/james/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope-MouseKeys/src/MouseWrapper.cpp:44: undefined reference to `Mouse' /home/james/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope-MouseKeys/src/MouseWrapper.cpp:44: undefined reference to `Mouse' /home/james/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope-MouseKeys/src/MouseWrapper.cpp:44: undefined reference to `Mouse_::release(unsigned char)' libraries/Kaleidoscope-MouseKeys/Kaleidoscope-MouseKeys.a(MouseWrapper.cpp.o): In function `MouseWrapper_::warp_jump(unsigned int, unsigned int, unsigned int, unsigned int)': /home/james/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope-MouseKeys/src/MouseWrapper.cpp:44: undefined reference to `AbsoluteMouse' /home/james/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope-MouseKeys/src/MouseWrapper.cpp:44: undefined reference to `AbsoluteMouse' /home/james/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope-MouseKeys/src/MouseWrapper.cpp:44: undefined reference to `AbsoluteMouse_::moveTo(unsigned int, unsigned int, signed char)' libraries/Kaleidoscope-MouseKeys/Kaleidoscope-MouseKeys.a(MouseWrapper.cpp.o): In function `MouseWrapper_::move(signed char, signed char)': /home/james/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope-MouseKeys/src/MouseWrapper.cpp:110: undefined reference to `Mouse' /home/james/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope-MouseKeys/src/MouseWrapper.cpp:110: undefined reference to `Mouse' /home/james/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope-MouseKeys/src/MouseWrapper.cpp:110: undefined reference to `Mouse_::move(signed char, signed char, signed char)' collect2: error: ld returned 1 exit status exit status 1 Error compiling for board Keyboardio Model 01.

Docs have some inconsistencies on flashing firmware

I recently tried to flash the firmware and was super confused from the docs whether I should use the makefile or flash from the Arduino app. Some consistency and clarity would be super helpful, as would a note that holding down the prog button is necessary to successfully flash.

Thanks!

ConsumerControl does not repeat

At the moment, ConsumerControl keys are not repeating, because we use ConsumerControl.write(), and only when the key toggles on. This means that if I want to fiddle with volume control (iirc that is part of ConsumerControl, but SystemControl suffers from the same issue), I need to repeatedly tap a key, instead of being able to hold it.

I think we should be using .press(), and .releaseAll() in the loop, like we do for Keyboard, but I have to test if this works as one would expect.

Releasing `fn` before key enters 2 characters

@bergey writes:

On the PVT with default firmware, on Windows 10, releasing the fn key while still holding one of uiopprints both characters - {u, [o- and so forth. I find I roll my hand in a way that I do this frequently. Does anyone want this behavior

Instructions for Linux Setting the UDEV rules

Currently in Linux when you try to program the keyboard, you will get a programming error.

The error looks similar to this.

Sketch uses 20684 bytes (72%) of program storage space. Maximum is 28672 bytes.
Global variables use 1700 bytes (66%) of dynamic memory, leaving 860 bytes for local variables. Maximum is 2560 bytes.
processing.app.debug.RunnerException
at cc.arduino.packages.uploaders.SerialUploader.uploadUsingPreferences(SerialUploader.java:160)
at cc.arduino.UploaderUtils.upload(UploaderUtils.java:78)
at processing.app.SketchController.upload(SketchController.java:713)
at processing.app.SketchController.exportApplet(SketchController.java:686)
at processing.app.Editor$DefaultExportHandler.run(Editor.java:2149)
at java.lang.Thread.run(Thread.java:745)
Caused by: processing.app.SerialException: Error touching serial port '/dev/ttyACM0'.
at processing.app.Serial.touchForCDCReset(Serial.java:99)
at cc.arduino.packages.uploaders.SerialUploader.uploadUsingPreferences(SerialUploader.java:144)
... 5 more
Caused by: jssc.SerialPortException: Port name - /dev/ttyACM0; Method name - openPort(); Exception type - Permission denied.
at jssc.SerialPort.openPort(SerialPort.java:170)
at processing.app.Serial.touchForCDCReset(Serial.java:93)
... 6 more

The wiki doesn't have any instructions on how to add this.
I'm going to add a wiki page on how to add a udev rule to linux. I have done this for work a couple of times.

Left hand modifiers + right hand keys question

I got the following question on the wiki of my fork, from @NicholasSterling, copying it here to make it easier to answer:


  1. Can left-hand modifiers affect right-hand keys (and vice versa)?

In Model01.cpp, act_on_matrix_scan() makes two calls to handle_key_event -- the first takes the left-hand state, and the second takes the right-hand state. Does that mean that we could not have Ctrl and Alt under the left thumb and Shift under the right thumb, and use them to produce, say Ctrl-Alt-Shift-L?

Consider some sort of "tap" helper

      handle_keyswitch_event (Key_Backspace, UNKNOWN_KEYSWITCH_LOCATION, IS_PRESSED | INJECTED);
      Keyboard.sendReport ();
      handle_keyswitch_event (Key_Backspace, UNKNOWN_KEYSWITCH_LOCATION, WAS_PRESSED | INJECTED);
      Keyboard.sendReport ();

is a pattern we repeat more than a few times. Perhaps we should have a helper for it

Pressing fn should allow use of ctrl/cmd/alt/shift still

I have some key bindings for meta keys + arrow keys or brackets. It is currently impossible to execute these key bindings with keyboardio 01 because pressing fn disables the meta keys. There is nothing mapped to those keys in the fn down mode, so why not have them be active in both states?

Error building mouse_movement.o

[0] $ make
/usr/bin/avr-g++ -c -g -w -Wa,-adhlns=build/mouse_movement.lst -DVERSION=\"e220-dirty\" -DUSB_VID=0x1209 -DUSB_PID=0x2301 '-DUSB_PRODUCT="Keyboardio model01"'  -DARDUINO_ARCH_AVR -DUSING_MAKEFILE=1 -Wall -Wextra -Wformat=2 -Wuninitialized -Wshadow -Wconversion  -Os -freorder-blocks -fno-inline-small-functions -fno-exceptions -ffunction-sections -fdata-sections -MMD -DF_CPU=16000000L -DARDUINO=165   -mmcu=atmega32u4 -I/usr/share/arduino/hardware/arduino/avr/libraries/EEPROM -I/usr/share/arduino/hardware/arduino/avr/libraries/Wire -I/usr/share/arduino/hardware/arduino/avr/libraries/SPI -I/usr/share/arduino/hardware/arduino/avr/libraries/SoftwareSerial -I/usr/share/arduino/hardware/arduino/avr/libraries/EEPROM -I/usr/share/arduino/hardware/arduino/avr/libraries/Wire -I/usr/share/arduino/hardware/arduino/avr/libraries/EEPROM -I/usr/share/arduino/hardware/arduino/avr/libraries/Wire -I/usr/share/arduino/hardware/arduino/avr/libraries/Wire/utility -I/usr/share/arduino/hardware/arduino/avr/libraries/Wire/utility -I/usr/share/arduino/hardware/arduino/avr/libraries/Wire/utility -Ihardware/keyboardio/avr/variants/model01  -Ihardware/keyboardio/avr/cores/keyboardio -MD -MT 'build/libsketch.a/(mouse_movement.o)' -MF build/libsketch.a/._mouse_movement.dep mouse_movement.cpp -o build/mouse_movement.o
mouse_movement.cpp:157:1: fatal error: opening dependency file build/libsketch.a/._mouse_movement.dep: No such file or directory
 }
 ^
compilation terminated.
_Makefile.Master:661: recipe for target 'build/libsketch.a/(mouse_movement.o)' failed
make: *** [build/libsketch.a/(mouse_movement.o)] Error 1

I'm not sure why this is specifically missing or why there are parens around the file name.

Simplifying - hopefully - some event handling scenarios

I've been trying to make the Akela plugins work, and one issue I ran into is that injecting events is not the most straightforward thing. Or, rather, injecting is reasonably straightforward, but changing one key into another, is not. Reinjecting a new one has a number of issues, ranging from making it too easy to create endless loops, to not handling keys we should, for fear of an endless loop.

So, I thought that if the handlers would not return bool, but a Key, one that would be passed on to the next handler, that would solve most of my problems. Seeing a Key_NoKey would short circuit the loop.

I have not tried this method yet, but its yet another change around event handling, so I figured I'll open an issue first.

Fn release deactivates layer even if other Fn still held

I just noticed a bug in how the Fn keys are handled. Press one Fn, press the other, then release one. The Fn modifier state should still be active, but it's not.

FWIW, I'm using Fn=Key_Keymap1_Momentary instead of Fn=Key_KeymapNext_Momentary, to avoid having dual-Fn turn on numlock.

For @algernon , context from IRC:

<algernon> regarding the Fn keys: that's going to be a tricky fix.
<algernon> or perhaps not...
<algernon> anyway, the root of the issue is that both keys have the same keycode, and the layer code turns the layer off when the keycode is released (it doesn't care where that release originates from)
<algernon> it also turns the layer on only on key press, not when its held, so the other Fn key being held does not re-trigger the layer
<algernon> one workaround would be to call layer.on() not only when the layer key toggles on, but every cycle while it is held
<algernon> that would fix the issue, but I'm not sure about the costs yet.
<ToyKeeper> Maybe it could use a counter instead of a flag?  Bump up on each press, down on each release, and the layer is active whenever the count is non-zero?
<algernon> yeah... doing so would trigger mergeLayers() each cycle, which would be costy.
<ToyKeeper> I haven't looked at that part of the code at all; no idea how it works.
<algernon> using a counter would mean we need a counter for each layer key, of which there may be... many.
<algernon> and we can't know ahead of time how many layer keys we'd have.
<algernon> an easier solution would likely be to keep track of previous layer state, and only call mergeLayers if that changes
<algernon> that's only an uint32_t and a comparison away, easier and smaller than a counter.
<algernon> OTOH, if one Fn is released, we'd clear the layer first, continue processing keys until we reach the other, and only then re-enable the layer.
<algernon> that would not be good, either.
<algernon> so perhaps we should delay layer toggling to the end of the cycle..
<algernon> ToyKeeper: can you report it as a bug against Kaleidoscope?
<algernon> I'll dump the above monologue into it then, so its captured in an issue too.
<ToyKeeper> Yeah, I was just checking if other keyboards do the same thing.  It seems some do, some don't.  (with other mod keys)

Keyboardio vs libinput vs modemmanager

Investigate how to set up udev (if possible) so that ModemManager won't jump on keyboardio. At the moment when modemmanager is installed, the keyboard rarely manages to enumerate. May be a bug in modemmanager, too.

Another issue is libinput, which fails to handle the absolute positions coming from a relative device. See here for the patch that introduced this behavior. Removing the return from the error message improves things, but the virtual resolution is wrong - report both cases to libinput upstream.

Both issues will be handled by me, this is just a reminder, so I won't forget the progress we made so far.

Feature request: Quasi (aka Leep) key

Universal modifier key (Mod or Quasi, which name would be better?).


Main idea: "press Quasi", "press <trigger key> (e.g. Ctrl)", "release <trigger key>", "press <target key>" (with holden "Quasi") => acts like "modifier key" (from "trigger to modifier map" according to pressed <trigger key>) plus "<target key>".

It may be convenient when you need to hold few modifiers.
Example:

  • hold "Quasi"
  • press and release "Alt"
  • press and release "Ctrl"
  • press "D"
    => "Alt+Ctrl+D" as result.

we can customize "trigger to modifier map" to press e.g. "C" key for "Ctrl" modifier.

Here original idea author's blog. I'm not the author. Initially idea based on Jef Raskin's principles from "The Humane Interface".

Open Source license

Hi,

I hate to bother you with this question as I saw in one of the files in this project that you intend to attach an open source license when you release the board, but I could really use your code as it is right now.

I am building a keyboard using an Arduino Micro and an old typewriter (http://imgur.com/a/40a9m#k3JBMMv). I'd really like to use your code, but I'd have to fork it and add some code (I use a shift register for extra I/O) so if you could find a little bit of time to to assign a license to it I'd be very grateful and I promise I won't bug you with (more) issues or feature requests :)

Kind regards,
Tinco

Keyboardio-specific key_defs defined in Kaleidoscope headers

Kaleidoscope aims to be a keyboard-independent framework, but key_defs.h defines the following Keyboardio-specific Keys:

#define Key_LeftParen LSHIFT(Key_9)
#define Key_RightParen LSHIFT(Key_0)
#define Key_LeftCurlyBracket LSHIFT(Key_LeftBracket)
#define Key_RightCurlyBracket LSHIFT(Key_RightBracket)
#define Key_Pipe LSHIFT(Key_Backslash)

Not only would it make more sense from a modularity perspective to define these in Model01-Firmware/Model01-Firmware.ino, but in that location I think contributors are more likely to find it when looking for examples of how to create keys which type shifted characters without shift held down.

This would require also defining these in Kaleidoscope/examples/Kaleidoscope/Kaleidoscope.ino, which appears to be a kinda-duplication of Model01-Firmware.ino already anyway.

EventHandler: do the mappedKey lookup earlier

Currently, when handle_key_event is called, it does not touch the mappedKey argument, and defers the lookup to the first handler that needs the keycode. This is reasonable when the only handler that needs it is the default one, but if there are more handles, each may have to do their own lookup, or at least, have the logic to do a lookup if mappedKey is Key_NoKey.

To make things simpler, I believe that handle_key_event should have this logic, and the handlers should assume that the keycode they received is the one they should act upon, and avoid a lookup unless there is a good reason to do one.

Will submit a PR later, just recording the idea here, lest I forget it. This came up while working on one-shot keys, where the handler has to decide if it should handle the event, and it has to do an avoidable lookup right now.

Going in and out of numpad mode often sets the led color to red

Regardless of what the previous setting was, the keyboard will be in the red state after going in and out of numpad mode. This doesn't 100% consistently happen though. It seems to happen the first time after logging back into my computer but not again until I log out of my computer and come back to my desk later. So the problem may be with persisting the selected color scheme during computer sleep states?

Coding Style Guidelines

@obra mentioned on IRC the other day that Kaleidoscope could really use a coding style guide. Though some of it is enforced now via make astyle, that's mostly whitespace, and formatting. Naming, code organization, and similar things are not covered, and there are a number of different styles used throughout the codebase.

It would be incredibly useful not only for future authors, but for bringing the current set of plugins to a common ground, too.

(I'm going through a number of existing guides, and will share my opinion in followup comments)

Changing hooks from pre-allocated arrays to linked lists

One thing that made Kaleidoscope-Focus possible was the use of linked lists for hook-like things. I plan to experiment with changing the loop and eventHandler hooks into linked lists too, but first, want to document the reasons why, because like everything else, they come with a few trade-offs.

Pros:

  • No artificial limit of how many hooks one can have, except for the amount of SRAM.
  • Reasonably easy to insert hooks in the middle of the list.
    • This would make it possible to inject hooks before/after other hooks more easily, which would be great for features we may want to toggle on/off at run-time. Or for cases where we want to register the plugin late, but the hook early. Or when we always want the hook to register at the top.
  • Reduced memory footprint when using few (less than 8) hooks.

Cons:

  • Uses two bytes of SRAM / hook, instead of one, thus:
    • Increased memory use when using more than 8 hooks.
  • May need some additional macro-magic to make registration simpler.
    • We want to pass a (hook, nextItem) tuple, but only have the hook, so we use a macro to turn that into a list-item struct.
    • On the plus side, this can be baked into the existing hook defines, that are currently in the headers for compatibility reasons. Thus, plugins would not need to be updated immediately.

The code to handle them would not be terribly different, as far as I see.

Need to manual run make for bootloader

After following the instructions in the README, I needed to take the additional step of running make in the bootloaders/caterina directory to address a warning from the IDE about a missing Caterina.hex file.

(Not sure if this should be added to the instructions, or if this is a consequence of running verify without an actual device to test on)

Feature request: John Bumgarner's style key auto-repeat

The point: turn auto-repeat for symbol only after 3 presses. E.g. for "=" key,
user should press "=", release "=", press "=", release "=", hold "=".

Here we have 2 advantages:

  • we can't accidentally start key repeating just by eventually holding key.
  • we have two press intervals, so it's enough to approximate desired key repeating expected speed (yep, we able interactive choose key repeating speed).

And it still it's pretty easy yet to press same key 3 times.

Surely, it require turning off software key auto repeating in OS for best UX.

Layer lookup speed

At the moment, when we look up a key, we look at each layer from the highest active one, to the lowest. Every cycle. For the base layer, this is no extra work, but the higher the top layer is, the more work we have to perform each cycle, for each key.

This is suboptimal, the number of active layers should not affect the speed of the scan cycle, or at least not this much.

So I propose a solution, which may not be the most efficient (it requires ROWS * COLS number of bytes, or half the size of a layer), but will net us a lot higher speed, even when using many layers: we'll keep an index of what layer each key has been found at, and only do the more expensive lookup, if the index is marked invalid.

We'll use a byte array, and whenever we change layers, we clear the array (fill it with 0xff). The next scan cycle will do the expensive lookups, yes, but all the other scans that happen inbetween this expensive one, and the next that changes the layer state, will have a much easier job.

Even for a short, momentary layer switch, this would mean that we have half a dozen faster cycles.

This comes at a cost of some data space, however. We can optimize it further later, by using less bits / index, but I'd do that as a separate step.

Keyboardio.use is not type safe

Noticed by @obra, Keyboardio.use is not type safe: you can give it anything, and it will try to cast it to a KeyboardioPlugin *, and call ->begin() on it. The first argument must be of correct type, but the rest aren't checked, nor enforced.

See here for pointers about how to best fix it.

Add `Miami` theme

Would be nice to have a LED color mode corresponding to the popular Miami keycaps.

Investigate lagginess

@obra noticed that the current firmware feels a little laggier than previously, even with the layer lookup speedups. This may very well be the case, because handle_key_events runs through plugins, and we do two runs over the loop hooks every cycle, which may slow things down. Should investigate which part is slow, and what can be done to speed things up.

As a first step, Serial.println(millis()) here and there may shed some light on which part to look at first.

(And this issue is mostly a reminder for myself not to forget doing this.)

Mute key not working

Volume up and down work fine. The mute button doesn't seem to do anything in OSX 10.12.5

Consider the merits of a mono-repository

Rationale

I've found it frustrating to hack on the code. I may be overly opinionated as my day job is building source control systems at a large company that loves monorepos. However, I do feel like it is more difficult to work on this project than the big repos at work!

  1. Many of the things I've wanted to change need to be coordinated across multiple projects
  2. Keeping track of something that is one logical change locally means maintaining N+1 branches; 1 for each of the touched repos, plus an additional one in the Arduino-Boards repo that tracks them.
  3. Github has no support for dependent PRs.
  4. Travis-CI has no support for subrepos or dependent PRs.
  5. Tracking and rebasing in the current model is pretty high friction; trying to rebase some work I have for the event dispatcher PR is taking way too long considering the magnitude of the changes

Proposal

That we re-unite the projects that are referenced from Arduino-Boards into a single repo.

This script: https://gist.github.com/wez/81fcfdd90e5ae9cbc6fd614beacdf1fe
produced this branch as an example of what things might look like: https://github.com/wez/Kaleidoscope/tree/unify

Implications

  1. Changes across multiple libraries/plugins can now be submitted as a single PR
  2. A single PR is easier for a human to review; fewer places to visit to understand the impact of that change vs. consuming multiple PRs with dependency or CI test results
  3. Travis-CI can be configured for just the main repo and can more easily be made to build and test PRs and commits, easing the review burden
  4. The getting started instructions will be much simpler; check out a single repo and run make (or some script in the top level dir).
  5. The history of the repo is preserved by the script, but github doesn't use the --follow flag in its history view. Blame is correctly attributed, but you'll need to run some manual git log --follow commands to review history, should you need to review history. It is possible for the migration script to use git filter-branch to rewrite the paths in the history to workaround this, but it is labor intensive to deal with conflicting paths in the history with that approach. (I tried this and decided it was too much work to do without getting buy-in from the other contributors!)

Concerns

What does this mean for Arduino IDE users that are consuming this project?

Today, it is technically possible for someone to download and use one of the libraries and use it independently from the rest of the Kaleidoscope project.

With a unified repo this is still possible, but slightly more work: they just have to move the libraries subdirectory of interest out of the repo and put it in their own libraries folder.

Building a firmware project is easiest to do from the command line. There are too many libraries to manually copy into the local sketch library folder today, so I don't believe that anyone would want to maintain those by hand. If that is a flow we want to support, we can write a little script to symlink things to make it look right.

Will this encourage poor layering/encapsulation choices when hacking on the code?

One argument for having separate repos is that it forces the code to be more modular.
Moving to a unified repo makes it easier to make a change anywhere in the repo but doesn't inherently lead to poor choices; they're still possible in both models. For the reasons I mentioned in the rationale section, I am more inclined to put code into the wrong module just so that I can reduce the number of PRs I'd have to deal with. Moving to a monorepo means that I can more easily prepare a series of small well-encapsulated commits.

Other questions?

Please add them below as comments!

README has bad instructions

Following the instructions in README.md on macOS yields an error on the last step:

Makefile:13: /Users/merlin/Documents/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope-Plugin/build/rules.mk: No such file or directory
make: *** No rule to make target `/Users/merlin/Documents/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope-Plugin/build/rules.mk'. Stop.

I haven't had time to investigate, but presumably there's at least one step that has been skipped because a file is normally there when you guys do it, but isn't there for someone starting from scratch.

Loop hook thoughts

I have a couple of plugins that would need to hook into the loop() hooks, because their functionality does not depend on keys being pressed. Or at least, the action they trigger is best caught in the loop, where the full state is available.

Some of these plugins need to see the report (to check modifier state, for example, so they can light up LEDs), some would need to register keys for the next iteration (to keep one-shots pressed, for example)

For both of these to work, I'd need either two sets of hooks (yuck!), or call each twice, with an appropriate parameter, so the hooks themselves can decide whether to act or not. I'd prefer this, because I have a few ideas which would benefit from running the same function twice, in both places.

What do you think?

Replacing loop/event-handler hooks, and more helpers

While trying to work out how to implement one-shot keys nicely, I ran into a couple of shortcomings with the current - very simplistic - hook helpers: the API only allows appending hooks, but to toggle one-shots on and off, I'd need a way to replace an existing hook, too.

While there, deleting a hook, and prepending (or rather, inserting at a specific position) would also be useful. So I'm proposing the following additional helpers, which I will implement at the first opportunity, too:

// delete all occurrences of the hook function from the array, pulling up later handlers
void event_handler_hook_delete (custom_handler_t hook);

// replace one hook with another
void event_handler_hook_replace (custom_handler_t old, custom_handler_t new);

// insert a hook at a specific index, pushing down the rest, if need be
void event_handler_hook_insert (byte idx, custom_handler_t hook);

...and the same for the loop() hooks.

In a plugin, one would use them like this:

void OneShotMods::on() {
  if (isOn)
    return;

  event_handler_hook_replace (this->passthroughHandler, this->oneShotHandler);
  loop_hook_add (this->oneShotLoop);
  isOn = true;
}

void oneShotMods::off() {
  if (!isOn)
    return;

  event_handler_hook_replace (this->oneShotHandler, this->passthoughHandler);
  loop_hook_delete (this->oneShotLoop);
  isOn = false;
}

While here, it may make plugin authors' life more convenient, if the _replace stuff would delete if the second argument is NULL, and add, if the first one is. Why? Because then, we can introduce a helper:

void hooks_replace (custom_handler_t oldEvent, custom_handler_t newEvent,
                    custom_loop_t oldLoop, custom_loop_t newLoop);

With this, the above code could be simplified to:

void OneShotMods::on() {
  if (isOn)
    return;

  hooks_replace (this->passthroughHandler, this->oneShotHandler,
                 NULL, this->oneShotLoop);
  isOn = true;
}

void oneShotMods::off() {
  if (!isOn)
    return;

  hooks_replace (this->oneShotHandler, this->passthroughHandler,
                 this->oneShotLoop, NULL);
  isOn = false;
}

We could even have a #define NO_HANDLER NULL to make the code look even nicer.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.