diff --git a/boards/ZFR_KBD/RP2.65-F/kb.py b/boards/ZFR_KBD/RP2.65-F/kb.py index 09214b2..d0c1f69 100644 --- a/boards/ZFR_KBD/RP2.65-F/kb.py +++ b/boards/ZFR_KBD/RP2.65-F/kb.py @@ -32,9 +32,74 @@ class KMKKeyboard(_KMKKeyboard): rgb_num_pixels = 70 coord_mapping = [ - 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, - 24, 17, 25, 18, 26, 19, 27, 20, 28, 21, 29, 22, 23, 31, - 40, 33, 41, 34, 42, 35, 43, 36, 44, 37, 45, 38, 46, 39, 47, - 56, 49, 57, 50, 58, 51, 59, 52, 60, 53, 61, 54, 55, 63, - 72, 65, 73, 74, 75, 76, 69, 77, 78, 71, 79, + 0, + 8, + 1, + 9, + 2, + 10, + 3, + 11, + 4, + 12, + 5, + 13, + 6, + 14, + 7, + 15, + 24, + 17, + 25, + 18, + 26, + 19, + 27, + 20, + 28, + 21, + 29, + 22, + 23, + 31, + 40, + 33, + 41, + 34, + 42, + 35, + 43, + 36, + 44, + 37, + 45, + 38, + 46, + 39, + 47, + 56, + 49, + 57, + 50, + 58, + 51, + 59, + 52, + 60, + 53, + 61, + 54, + 55, + 63, + 72, + 65, + 73, + 74, + 75, + 76, + 69, + 77, + 78, + 71, + 79, ] diff --git a/kmk/modules/potentiometer.py b/kmk/modules/potentiometer.py index 8263a15..a6a3588 100644 --- a/kmk/modules/potentiometer.py +++ b/kmk/modules/potentiometer.py @@ -1,9 +1,9 @@ -import busio from analogio import AnalogIn from supervisor import ticks_ms from kmk.modules import Module + class BasePotentiometer: def __init__(self, is_inverted=False): self.is_inverted = is_inverted @@ -11,23 +11,24 @@ class BasePotentiometer: self._direction = None self._pos = 0 self._timestamp = ticks_ms() - + # callback function on events. Needs to be defined externally self.on_move_do = None - + def get_state(self): return { 'direction': self.is_inverted and -self._direction or self._direction, 'position': self.is_inverted and -self._pos or self._pos, } - + def get_pos(self): - """Read from the analog pin assingned, truncate to 7 bits, + ''' + Read from the analog pin assingned, truncate to 7 bits, average over 10 readings, and return a value 0-127 - """ + ''' return int(sum([(self.read_pin.value >> 9) for i in range(10)]) / 10) - def update_state(self): + def update_state(self): self._direction = 0 new_pos = self.get_pos() if abs(new_pos - self._pos) > 2: @@ -39,7 +40,8 @@ class BasePotentiometer: self._pos = new_pos if self.on_move_do is not None: self.on_move_do(self.get_state()) - + + class GPIOPotentiometer(BasePotentiometer): def __init__(self, pin, move_callback, is_inverted=False): super().__init__(is_inverted) @@ -48,11 +50,12 @@ class GPIOPotentiometer(BasePotentiometer): self.cb = move_callback self.on_move_do = lambda state: self.cb(state) + class PotentiometerHandler(Module): def __init__(self): self.potentiometers = [] self.pins = None - + def on_runtime_enable(self, keyboard): return @@ -62,9 +65,9 @@ class PotentiometerHandler(Module): def during_bootup(self, keyboard): if self.pins: for args in self.pins: - self.potentiometers.append( GPIOPotentiometer(*args) ) + self.potentiometers.append(GPIOPotentiometer(*args)) return - + def before_matrix_scan(self, keyboard): ''' Return value will be injected as an extra matrix update @@ -90,4 +93,4 @@ class PotentiometerHandler(Module): return def on_powersave_disable(self, keyboard): - return \ No newline at end of file + return diff --git a/user_keymaps/ZFR_KBD/RP2.65-F.py b/user_keymaps/ZFR_KBD/RP2.65-F.py index 9c12002..a6779cb 100644 --- a/user_keymaps/ZFR_KBD/RP2.65-F.py +++ b/user_keymaps/ZFR_KBD/RP2.65-F.py @@ -1,28 +1,30 @@ import board - -import ulab.numpy as np - -from adafruit_hid.consumer_control_code import ConsumerControlCode -from adafruit_hid.consumer_control import ConsumerControl import usb_hid +import ulab.numpy as np +from adafruit_hid.consumer_control import ConsumerControl +from adafruit_hid.consumer_control_code import ConsumerControlCode from kb import KMKKeyboard -from kmk.keys import KC from kmk.extensions.RGB import RGB, AnimationModes -from kmk.modules.potentiometer import PotentiometerHandler +from kmk.keys import KC from kmk.modules.layers import Layers from kmk.modules.midi import MidiKeys +from kmk.modules.potentiometer import PotentiometerHandler keyboard = KMKKeyboard() keyboard.modules.append(Layers()) keyboard.modules.append(MidiKeys()) rgb_ext = RGB( - val_default=10, val_limit=100, # out of 255 - pixel_pin=keyboard.rgb_pixel_pin, num_pixels=keyboard.rgb_num_pixels, - refresh_rate=30, animation_speed=3, - animation_mode=AnimationModes.STATIC) + val_default=10, + val_limit=100, # out of 255 + pixel_pin=keyboard.rgb_pixel_pin, + num_pixels=keyboard.rgb_num_pixels, + refresh_rate=30, + animation_speed=3, + animation_mode=AnimationModes.STATIC, +) keyboard.extensions.append(rgb_ext) _______ = KC.TRNS @@ -42,6 +44,7 @@ MIDI = KC.TG(MIDI_LAYER_IDX) RGB_TOG = KC.RGB_TOG RAINBOW = KC.RGB_MODE_RAINBOW + def get_kb_rgb_obj(keyboard): rgb = None for ext in keyboard.extensions: @@ -50,6 +53,7 @@ def get_kb_rgb_obj(keyboard): break return rgb + cc = ConsumerControl(usb_hid.devices) keyboard.last_level = -1 @@ -63,6 +67,7 @@ level_inc_step = 1 level_lut = [int(x) for x in np.linspace(0, level_steps, 64).tolist()] + def set_sys_vol(state): # convert to 0-100 new_pos = int((state['position'] / 127) * 64) @@ -87,26 +92,30 @@ def set_sys_vol(state): cmd = ConsumerControlCode.VOLUME_DECREMENT # print(f"Setting system volume {vol_direction} by {level_diff} to reach {level}") - for i in range( int(level_diff / level_inc_step) ): + for i in range(int(level_diff / level_inc_step)): cc.send(cmd) keyboard.last_level = level return - + + # LEDs Color or animation speed hue_lut = [int(x) for x in np.linspace(0, 360, 127).tolist()] + + def set_led_var(state): rgb = get_kb_rgb_obj(keyboard) if rgb is None: return if rgb.animation_mode == AnimationModes.STATIC: - rgb.hue = hue_lut[ state['position'] ] + rgb.hue = hue_lut[state['position']] else: rgb.animation_speed = int((state['position'] / 127) * 5) rgb._do_update() return + def set_led_brightness(state): rgb = get_kb_rgb_obj(keyboard) if rgb is None: @@ -116,14 +125,17 @@ def set_led_brightness(state): rgb._do_update() return + def slider_1_handler(state): - set_sys_vol(state) - + set_sys_vol(state) + + # reserve middle four values - software detent pb_lut = [] pb_lut[00:29] = [int(x) for x in np.linspace(0, 8192, 30).tolist()] -pb_lut[30:33] = [8192 for x in range(4)] # midpoint - no bend -pb_lut[34:63] = [int(x) for x in np.linspace(8192, 8192*2, 30)] +pb_lut[30:33] = [8192 for x in range(4)] # midpoint - no bend +pb_lut[34:63] = [int(x) for x in np.linspace(8192, 8192 * 2, 30)] + def slider_2_handler(state): if keyboard.active_layers[0] == MIDI_LAYER_IDX: @@ -133,17 +145,21 @@ def slider_2_handler(state): bend = pb_lut[bend_idx] key = KC.MIDI_PB(bend) keyboard.tap_key(key) - else: + else: set_led_var(state) + keyboard.__midi_velocity = 0 + + def slider_3_handler(state): if keyboard.active_layers[0] == MIDI_LAYER_IDX: # use as MIDI note velocity keyboard.__midi_velocity = int((state['position'] / 127) * 127) - else: + else: set_led_brightness(state) + faders = PotentiometerHandler() faders.pins = ( (board.RV1, slider_1_handler, False), @@ -152,54 +168,378 @@ faders.pins = ( ) keyboard.modules.append(faders) + def set_midi_vel(key, keyboard, *args): key.meta.velocity = keyboard.__midi_velocity return True -def MN(note : str): + +def MN(note: str): midi_keypress = KC.MIDI_NOTE(note, 1) midi_keypress.before_press_handler(set_midi_vel) return midi_keypress - + + keyboard.keymap = [ - [ # Base Layer - KC.ESC, KC.GRAVE, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, KC.BSLS, KC.DEL, KC.MINS, KC.EQUAL, - KC.TAB, KC.Q, KC.W, KC.E, KC.R, KC.T, KC.Y, KC.U, KC.I, KC.O, KC.P, KC.BACKSPACE, KC.LBRC, KC.RBRC, - KC.LCTRL, KC.A, KC.S, KC.D, KC.F, KC.G, KC.H, KC.J, KC.K, KC.L, KC.SCLN, KC.QUOT, KC.ENTER, KC.QUOT, KC.HOME, - KC.LSFT, KC.Z, KC.X, KC.C, KC.V, KC.B, KC.N, KC.M, KC.COMM, KC.DOT, KC.SLSH, KC.RSFT, KC.UP, KC.END, - FN1, KC.LGUI, KC.LALT, KC.SPC, KC.ENTER, KC.RGUI, KC.RALT, FN2, KC.LEFT, KC.DOWN, KC.RIGHT, + [ # Base Layer + KC.ESC, + KC.GRAVE, + KC.N1, + KC.N2, + KC.N3, + KC.N4, + KC.N5, + KC.N6, + KC.N7, + KC.N8, + KC.N9, + KC.N0, + KC.BSLS, + KC.DEL, + KC.MINS, + KC.EQUAL, + KC.TAB, + KC.Q, + KC.W, + KC.E, + KC.R, + KC.T, + KC.Y, + KC.U, + KC.I, + KC.O, + KC.P, + KC.BACKSPACE, + KC.LBRC, + KC.RBRC, + KC.LCTRL, + KC.A, + KC.S, + KC.D, + KC.F, + KC.G, + KC.H, + KC.J, + KC.K, + KC.L, + KC.SCLN, + KC.QUOT, + KC.ENTER, + KC.QUOT, + KC.HOME, + KC.LSFT, + KC.Z, + KC.X, + KC.C, + KC.V, + KC.B, + KC.N, + KC.M, + KC.COMM, + KC.DOT, + KC.SLSH, + KC.RSFT, + KC.UP, + KC.END, + FN1, + KC.LGUI, + KC.LALT, + KC.SPC, + KC.ENTER, + KC.RGUI, + KC.RALT, + FN2, + KC.LEFT, + KC.DOWN, + KC.RIGHT, ], - - [ # FN1 Layer - _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, - _______, _______, _______, RGB_TOG, RAINBOW, _______, _______, _______, _______, _______, _______, _______, _______, _______, - _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, - _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, - XXXXXXX, _______, _______, _______, _______, _______, _______, FN3, _______, _______, _______, + [ # FN1 Layer + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + RGB_TOG, + RAINBOW, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + XXXXXXX, + _______, + _______, + _______, + _______, + _______, + _______, + FN3, + _______, + _______, + _______, ], - - [ # FN2 Layer - _______, _______, KC.F1 , KC.F2 , KC.F3 , KC.F4 , KC.F5 , KC.F6 , KC.F7 , KC.F8 , KC.F9 , KC.F10 , KC.F11 , KC.F12 , _______, _______, - _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, - _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, - _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, - FN3, _______, _______, _______, _______, _______, _______, XXXXXXX, _______, _______, _______, + [ # FN2 Layer + _______, + _______, + KC.F1, + KC.F2, + KC.F3, + KC.F4, + KC.F5, + KC.F6, + KC.F7, + KC.F8, + KC.F9, + KC.F10, + KC.F11, + KC.F12, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + FN3, + _______, + _______, + _______, + _______, + _______, + _______, + XXXXXXX, + _______, + _______, + _______, ], - - [ # FN3 Layer - _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, - _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, - _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, - _______, _______, _______, _______, _______, _______, _______, MIDI, _______, _______, _______, _______, _______, _______, - XXXXXXX, _______, _______, _______, _______, _______, _______, XXXXXXX, _______, _______, _______, + [ # FN3 Layer + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + _______, + MIDI, + _______, + _______, + _______, + _______, + _______, + _______, + XXXXXXX, + _______, + _______, + _______, + _______, + _______, + _______, + XXXXXXX, + _______, + _______, + _______, ], - - [ # MIDI Layer - MIDI, MN('E3'), MN('F#3'),MN('G#3'),MN('A#3'),XXXXXXX, MN('C#4'),MN('D#4'),XXXXXXX, MN('F#4'),MN('G#4'),MN('A#4'),MN('C5'),MN('C#5'), _______, _______, - _______, MN('F3'), MN('G3'), MN('A3'), MN('B3'), MN('C4'), MN('D4'), MN('E4'), MN('F4'), MN('G4'), MN('A4'), MN('B4'), _______, _______, - _______, XXXXXXX, MN('C#2'),MN('D#2'),XXXXXXX, MN('F#2'),MN('G#2'),MN('A#2'),XXXXXXX, MN('C#3'),MN('D#3'),XXXXXXX, _______, _______, _______, - _______, MN('B1'), MN('C2'), MN('D2'), MN('E2'), MN('F2'), MN('G2'), MN('A2'), MN('B2'), MN('C3'), MN('D3'), MN('E3'), _______, _______, - XXXXXXX, _______, _______, _______, _______, _______, _______, XXXXXXX, _______, _______, _______, + [ # MIDI Layer + MIDI, + MN('E3'), + MN('F#3'), + MN('G#3'), + MN('A#3'), + XXXXXXX, + MN('C#4'), + MN('D#4'), + XXXXXXX, + MN('F#4'), + MN('G#4'), + MN('A#4'), + MN('C5'), + MN('C#5'), + _______, + _______, + _______, + MN('F3'), + MN('G3'), + MN('A3'), + MN('B3'), + MN('C4'), + MN('D4'), + MN('E4'), + MN('F4'), + MN('G4'), + MN('A4'), + MN('B4'), + _______, + _______, + _______, + XXXXXXX, + MN('C#2'), + MN('D#2'), + XXXXXXX, + MN('F#2'), + MN('G#2'), + MN('A#2'), + XXXXXXX, + MN('C#3'), + MN('D#3'), + XXXXXXX, + _______, + _______, + _______, + _______, + MN('B1'), + MN('C2'), + MN('D2'), + MN('E2'), + MN('F2'), + MN('G2'), + MN('A2'), + MN('B2'), + MN('C3'), + MN('D3'), + MN('E3'), + _______, + _______, + XXXXXXX, + _______, + _______, + _______, + _______, + _______, + _______, + XXXXXXX, + _______, + _______, + _______, ], ]