WIP port to new firmware

wip-new-qmk
Jurij Podgoršek 2024-08-28 14:21:09 +02:00
parent a25b0f0778
commit 7dc6605977
28 changed files with 1956 additions and 663 deletions

View File

@ -0,0 +1,52 @@
#include "balthazar3.h"
/**
void matrix_init_kb(void) {
// put your keyboard start-up code here
// runs once when the firmware starts up
//setPinInputHigh(E6);
matrix_init_user();
}
**/
/**
void matrix_init_kb(void) {
// put your keyboard start-up code here
// runs once when the firmware starts up
// set the whole port F as input pulled high
//DDRF &= ~(1<<2);
//PORTF \|= (1<<2)
// enable Port F for input with pull ups activated
//DDRF = 0x00;
//PORTF = 0xff;
//noInterrupts();
// to set JTD -> disabling JTAG which may affect P:F4,F5,F7 - run this twice within 4 cycles
MCUCR |= (1<<JTD);
MCUCR |= (1<<JTD);
//interrupts();
// By default, the JTAG debugging interface is disabled as soon as the keyboard starts up.
// defined in tmk_core/common/keyboard.c as function disable_jtag
// To use PORTF disable JTAG with writing JTD bit twice within four cycles.
//#if (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega32U4__))
// MCUCR |= _BV(JTD);
// MCUCR |= _BV(JTD);
//#endif
// disable adc
ADCSRA = 0;
// The ATMega32u4 has an option to divide its clock speed, to conserve power. Like in the case of JTAG, this can be set or unset in fuses.
// Thankfully, like in the JTAG case, we can disable this at run-time too, with the following magic words:
//CLKPR = (1 << CLKPCE);
//CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);
matrix_init_user();
}
**/

View File

@ -0,0 +1,45 @@
/*
BALTHAZAR 2020 Turbosavski
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, either version 2 of the License, or
(at your option) any later version.
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/>.
*/
#pragma once
#include "quantum.h"
/* Layout moved to keyboard.json using the online converter: https://qmk.fm/converter/
More info: https://github.com/mechmerlin/qmk_setup/blob/master/info_json_tutorial.md */
// 7x11 => diode dir = ROW2COL
// we scan 7 rows left half 1-7 right half 1-7
// notation: K(col:01-11)(row:1-7)
#define KEYMAP( \
K011, K012, K013, K014, K015, K016, K017, K111, K112, K113, K114, K115, K116, K117, \
K031, K021, K022, K023, K024, K025, K026, K027, K101, K102, K103, K104, K105, K106, K107, \
K051, K041, K032, K033, K034, K035, K036, K037, K091, K092, K093, K094, K095, K096, K097, \
K061, K062, K042, K043, K044, K045, K046, K047, K081, K082, K083, K084, K085, K086, K087, \
K063, K052, K053, K054, K055, K056, K057, K071, K072, K073, K074, K075, K076, K077, \
K064, K065, K066, K067 \
) { \
{ K011, K021, K031, K041, K051, K061, K071, K081, K091, K101, K111 }, \
{ K012, K022, K032, K042, K052, K062, K072, K082, K092, K102, K112 }, \
{ K013, K023, K033, K043, K053, K063, K073, K083, K093, K103, K113 }, \
{ K014, K024, K034, K044, K054, K064, K074, K084, K094, K104, K114 }, \
{ K015, K025, K035, K045, K055, K065, K075, K085, K095, K105, K115 }, \
{ K016, K026, K036, K046, K056, K066, K076, K086, K096, K106, K116 }, \
{ K017, K027, K037, K047, K057, K067, K077, K087, K097, K107, K117 }, \
}
#define LAYOUT KEYMAP

View File

@ -0,0 +1,249 @@
/*
BALTHAZAR 2020/21/22
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, either version 2 of the License, or
(at your option) any later version.
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/>.
*/
#pragma once
/*
To use QMK keyboard on android or windows - use VID and PID from some more popular device - like Logitech G413.
Hm, not ok
VID PID
Logitech G413 -> 0x046D 0xC33A
Logitech G815 -> 0x046D 0xC33F
*/
/*
* Feature disable options
* These options are also useful to firmware size reduction.
*/
#define NO_ACTION_TAPPING // disable tap dance and other tapping features
#define NO_ACTION_ONESHOT // disable one-shot modifiers
// we can define DIRECT_PINS or matrix DIODE_DIRECTION
// they are mutually exclusive -> DIODE_DIRECTION denotes a matrix operation
// 7x11 ROW2COL
#define DIODE_DIRECTION ROW2COL
// key matrix size: we are forking to left and right
#define MATRIX_COLS 11 // pulled-up cols are inputs (unselected) and outputs: selecting - low = selected row; input high = unselected row
#define MATRIX_ROWS 7 // pulled-up rows are inputs for reading - key pressed = low detected for selected col
// selected COL pins are switched to output mode and to low; when unselected they are input mode pulled-up = high
//#define MATRIX_COL_PINS { C7, C6, B6, B5, B4, D6, D4, D7, D5, D2, D3 } // these are ok
#define MATRIX_COL_PINS { E2, C7, C6, B6, B5, B4, D7, D6, D4, B7, D3 } // these are ok
// ROW pins are input pulled-up high pins; they are read according to the selected COL
#define MATRIX_ROW_PINS { F0, F1, F4, F5, F6, F7, E6 }
// port F is problematic? Port F4,F5,F7 are also for JTAG testing interface - PF7 on one board not ok
// JTAG-capable MCUs come from the factory with the JTAGEN fuse set, and it takes over certain pins of the MCU that the board may be using for the switch matrix, LEDs, etc. - hfuse 0x99 (JTAG enabled) or 0xD9 (JTAG disabled)
// By default, with QMK the JTAG debugging interface is disabled as soon as the keyboard starts up.
// defined in tmk_core/common/keyboard.c as function disable_jtag
// port F pins are tristated just after reset. If JTAG activated pullup on F7, F5, F4 will be active even on reset.
// Port F pins now ok - pulled-up inputs - E6 can also be left pulled down -
// NO: can this be because of conflict with QMK DFU bootloader //#define QMK_LED E6
/**
INT6/AIN0 Port E, Bit 6
INT6, External Interrupt source 6: The PE6 pin can serve as an external interrupt source.
AIN0 Analog Comparator Negative input. This pin is directly connected to the negative input of the Analog
Comparator.
HWB Port E, Bit 2
HWB allows to execute the bootloader section after reset when tied to ground during external reset pulse. The
HWB mode of this pin is active only when the HWBE fuse is enable. During normal operation (excluded Reset),
this pin acts as a general purpose I/O.
Overriding Signals for Alternate Functions PE6, PE2
Signal Name PE6/INT6/AIN0 PE2/HWB
PUOE 0 0
PUOV 0 0
DDOE 0 0
DDOV 0 1
PVOE 0 0
PVOV 0 0
DIEOE INT6 ENABLE 0
DIEOV 1 0
DI INT6 INPUT* HWB
AIO AIN0 INPUT*
**/
// Debounce reduces chatter (unintended double-presses) - default: 5; set 0 if debouncing is not needed
#define DEBOUNCE 5
// delay in microseconds when between changing matrix pin state and reading values
// in matrix.c: just after select_col(current_col) and before reading rows for current_col
#define MATRIX_IO_DELAY 30 //default 30; 100, 1000 is 1ms, 1000000 is 1s
// sets the USB polling rate in milliseconds for the keyboard, mouse, and shared (NKRO/media keys) interfaces
//#define USB_POLLING_INTERVAL_MS 10
// sets the I2C clock rate speed for keyboards using I2C. The default is 400000L
// we may use it for PSU module
//#define F_SCL 100000L
//#define PS2_MOUSE_SCROLL_BTN_MASK (1<<PS2_MOUSE_BTN_MIDDLE) // Default
//#define DEBUG_MATRIX_SCAN_RATE // we get 1200 Hz to 500 Hz
/*
PB0 ISP ss - slave (SPI communication not used)
PB1 ISP sclk
PB2 ISP mosi
PB3 ISP miso
now PS/2:
PB1 ps/2 clock PCINT1
PB7 ps/2 data
*/
//#define LOCKING_SUPPORT_ENABLE
// Locking resynchronize hack
//#define LOCKING_RESYNC_ENABLE
//#define BACKLIGHT_PIN B0 -> SS
// PS2 trackpad
/*https://docs.qmk.fm/#/feature_ps2_mouse*/
/*
trackpad without native buttons. A touch on trackpad changes the F6, F7 keys to left and right buttons
*/
#ifdef PS2_MOUSE_ENABLE
// interrupt PS/2 touchpad
// You can use any INT or PCINT pin for clock, and any pin for data.
#ifdef PS2_USE_INT
#define PS2_CLOCK_PORT PORTB //PORTD
#define PS2_CLOCK_PIN PINB //PIND
#define PS2_CLOCK_DDR DDRB //DDRD
#define PS2_CLOCK_BIT 1
#define PS2_DATA_PORT PORTB //PORTD
#define PS2_DATA_PIN PINB //PIND
#define PS2_DATA_DDR DDRB //DDRD
#define PS2_DATA_BIT 7
#define PS2_INT_INIT() do { \
EICRA |= ((1<<ISC21) | \
(0<<ISC20)); \
} while (0)
#define PS2_INT_ON() do { \
EIMSK |= (1<<INT2); \
} while (0)
#define PS2_INT_OFF() do { \
EIMSK &= ~(1<<INT2); \
} while (0)
#define PS2_INT_VECT INT2_vect
#endif // end PS2_USE_INT
// usart PS/2 touchpad - we use interrupt above
#ifdef PS2_USE_USART
#define PS2_CLOCK_PORT PORTD
#define PS2_CLOCK_PIN D1
#define PS2_CLOCK_DDR DDRD
#define PS2_CLOCK_BIT 5
#define PS2_DATA_PORT PORTD
#define PS2_DATA_PIN D2
#define PS2_DATA_DDR DDRD
#define PS2_DATA_BIT 2
// synchronous, odd parity, 1-bit stop, 8-bit data, sample at falling edge.
// Set DDR of CLOCK as input to be slave
#define PS2_USART_INIT() do { \
PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT); \
PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT); \
UCSR1C = ((1 << UMSEL10) | \
(3 << UPM10) | \
(0 << USBS1) | \
(3 << UCSZ10) | \
(0 << UCPOL1)); \
UCSR1A = 0; \
UBRR1H = 0; \
UBRR1L = 0; \
} while (0)
#define PS2_USART_RX_INT_ON() do { \
UCSR1B = ((1 << RXCIE1) | \
(1 << RXEN1)); \
} while (0)
#define PS2_USART_RX_POLL_ON() do { \
UCSR1B = (1 << RXEN1); \
} while (0)
#define PS2_USART_OFF() do { \
UCSR1C = 0; \
UCSR1B &= ~((1 << RXEN1) | \
(1 << TXEN1)); \
} while (0)
#define PS2_USART_RX_READY (UCSR1A & (1<<RXC1))
#define PS2_USART_RX_DATA UDR1
#define PS2_USART_ERROR (UCSR1A & ((1<<FE1) | (1<<DOR1) | (1<<UPE1)))
#define PS2_USART_RX_VECT USART1_RX_vect
#endif // end PS2_USE_USART
// Additional mouse/ trackpad settings
// Use remote mode instead of the default stream mode
//#define PS2_MOUSE_USE_REMOTE_MODE
// Enable the scrollwheel or scroll gesture on your mouse or touchpad
#define PS2_MOUSE_ENABLE_SCROLLING
// Some mice will need a scroll mask to be configured. The default is 0xFF
//#define PS2_MOUSE_SCROLL_MASK 0x0F
// Applies a transformation to the movement before sending to the host
//#define PS2_MOUSE_USE_2_1_SCALING
// The time to wait after initializing the ps2 host
//#define PS2_MOUSE_INIT_DELAY 1000 // Default
// The available buttons for (trackpoint) are:
//#define PS2_MOUSE_BTN_LEFT 0
//#define PS2_MOUSE_BTN_RIGHT 1
//#define PS2_MOUSE_BTN_MIDDLE 2
// we use trackpad without native buttons - use F6 (KC_F7), F7 (KC_F7) and 6 (KC_6) buttons
// - once we sense movement on touchpad
//Scroll Button
//To disable the scroll button feature:
//#define PS2_MOUSE_SCROLL_BTN_MASK 0
//invert the X and Y axes:
//#define PS2_MOUSE_INVERT_X
//#define PS2_MOUSE_INVERT_Y
//reverse the scroll axes:
//#define PS2_MOUSE_INVERT_H
//#define PS2_MOUSE_INVERT_V
//Rotate Mouse Axes
//Transform the output of the device with a clockwise rotation of 90, 180, or 270 degrees.
//#define PS2_MOUSE_ROTATE 270 // Compensate for East-facing device orientation.
//#define PS2_MOUSE_ROTATE 180 // Compensate for South-facing device orientation.
//#define PS2_MOUSE_ROTATE 90 // Compensate for West-facing device orientation.
#endif // end PS2_MOUSE_ENABLE
#define OLED_FONT_H "keymaps/toucholed/glcdfont.c"

View File

@ -0,0 +1,15 @@
{
"keyboard_name": "Balthazar keyboard version 3",
"maintainer": "NXT",
"manufacturer": "BALTHAZAR",
"url": "https://balthazar.space/",
"usb": {
"vid": "0xFEED",
"pid": "0xBAFE",
"device_version": "0.0.3"
},
"description": "QMK_77KEYS",
"processor": "atmega32u4",
"bootloader": "caterina",
"layout": "LAYOUT_balthazar3"
}

View File

@ -0,0 +1,251 @@
/*
BALTHAZAR 2020-21 default
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, either version 2 of the License, or
(at your option) any later version.
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 QMK_KEYBOARD_H
// debug -> CONSOLE_ENABLE yes // in rules.mk
/*
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
// If console is enabled, it will print the matrix position and status of each key pressed
#ifdef CONSOLE_ENABLE
//uprintf("KL: kc: 0x%04X, col: %u, row: %u, pressed: %b, time: %u, interrupt: %b, count: %u\n", keycode, record->event.key.col, record->event.key.row, record->event.pressed, record->event.time, record->tap.interrupted, record->tap.count);
if(record->event.pressed > 0) {
uprintf("KL: keycode: 0x%04X, col: %u, row: %u, pressed: %b\n", keycode, record->event.key.col, record->event.key.row, record->event.pressed);
}
#endif
return true;
}
*/
/**
void keyboard_post_init_user(void) {
// Customise these values to desired behaviour
//debug_enable=true;
//debug_matrix=true;
//debug_keyboard=true;
//debug_mouse=true;
}
**/
/**
we have left and right split to 7 active pins (rows)
per each split row we have 11 cols to be read
all 77 matrix nodes are used
we could add another row or rather col
Programming usage is our focus:
Esc is ok, Tab is ok
Left Shift key is important - switches between:
- numbers and ¨ ! " # $ % & / ( ) = ? *
- small letters and their capitals
- < and > ...
Cap is of secondary importance
Ctrl and Alt are ok
GUI is important - switches between views
Right Shift key (KC_RSFT) can be used for something else AltGr -> KC_RALT or KC_ROPT or KC_ALGR
In the middle F6 and F7 act as mouse left and right buttons, 6 is middle button (scrolling) - above is touchpad
to the far left and right are loudspeakers
* rows are verticals
* 1 2 3 4 5 6 7 1 2 3 4 5 6 7
*
* EscF1 F2 F3 F4 F5 F6 F7 F8 F9 F10F11F12PScr
*
* Tab `  1  2  3  4  5  6  7  8  9  0  -  = Del
*
* ShftCap Q  W  E  R  T  Y  U  I  O  P  [  ] Back
*
* CtrlAlt A  S  D  F  G  H  J  K  L  ;  '  # Entr
*
* GUI \  Z  X  C  V  B  N  M  ,  .  / UP AltG
*
* SpcSpc  Spc                Spc  LFTDWNRGHT
* space keys are four parallel keys
*
* 7x11 = 7 rows scanning + 11 cols reading
*
* row 1 = Esc, Grave, Tab , Caps, Shift, Ctrl, N, J, U, 7, F1
* row 2 = F1, 1, Q, A, Nubs, Alt, M, K, I, 8, F8
* etc.
**/
/* We have:
DIODE_DIRECTION ROW2COL
MATRIX_ROWS 7
MATRIX_COLS 11
COLS: Left to right, ROWS: Top to bottom
matrix.h says:
- according to number of cols (<8, <16 or <32) we create a binary 8 bit, 16 bit or 32 bit variable to hold all row values that were read
- for each col - get all row values
- col to row: Set row, read cols -> read_cols_on_row
- row to col: Set col, read rows -> read_rows_on_col
- matrix.c sets all row and col pins to pulled-up input mode, sets the selected active pin (set row or set col) as output low
- then reads the (read cols or rows) for 0 -> button pushed on that input pin -> pulled down via diode
In my situation i wanted to have COL as active select/ unselect outputs with high as selected and reading ROWS inputs as normally LOW for HIGH state - the diodes face COL2ROW and additional resistors are there to pull down inputs. Now resistors are not needed.
If i changed the direction of diodes - all would be ok: 7 LOW scanning outputs would be as envisioned
So i adapted to QMK: Our scanning output pins COLS become input reading pins ROWS and our input pins ROWS become scanning output pins COLS. We always have 7 input reading pins and 11 output scanning pins.
- we can exchange definitions of COLS pins and ROWS pins and then define diode direction to COLS2ROWS MATRIX_ROWS 11 MATRIX_COLS 7
- or keep it as now defined : diode direction ROWS2COLS MATRIX_ROWS 7 MATRIX_COLS 11
- in both we have 11 scanning outputs and 7 inputs to remember
- if another set of keys needed i would add 8th input line with options for 11 more keys (88)
- or 12th output line with option for 7 more keys (84)
- or have 8 x 10 = 80 - 3 more keys
- but 7 x 11 = 77 is ideal
*/
// direct matrix description - without macro -> ROW2COL
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = { // 7x11 ISO
{ KC_ESC, KC_GRV, KC_TAB, KC_CAPS, KC_LSFT, KC_LCTL, KC_N, KC_J, KC_U, KC_7, KC_F7 },
{ KC_F1, KC_1, KC_Q, KC_A, KC_NUBS, KC_LALT, KC_M, KC_K, KC_I, KC_8, KC_F8 },
{ KC_F2, KC_2, KC_W, KC_S, KC_Z, KC_LGUI, KC_COMM, KC_L, KC_O, KC_9, KC_F9 },
{ KC_F3, KC_3, KC_E, KC_D, KC_X, KC_SPC, KC_DOT, KC_SCLN, KC_P, KC_0, KC_F10 },
{ KC_F4, KC_4, KC_R, KC_F, KC_C, KC_LEFT, KC_SLSH, KC_QUOT, KC_LBRC, KC_MINS, KC_F11 },
{ KC_F5, KC_5, KC_T, KC_G, KC_V, KC_DOWN, KC_UP, KC_NUHS, KC_RBRC, KC_EQL, KC_F12 },
{ KC_F6, KC_6, KC_Y, KC_H, KC_B, KC_RIGHT, KC_ALGR, KC_ENT, KC_BSPC, KC_DEL, KC_PSCR },
}
};
/**
// indirect with row and cols role reversed -> COL2ROW
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT_all(
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_PSCR,
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_DEL,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSPC,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, KC_ENT,
KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_UP, KC_ALGR,
KC_LCTL, KC_LALT, KC_LGUI, KC_SPC, KC_LEFT, KC_DOWN, KC_RGHT
),
};
**/
/**
AltGr (KC_ALGR) prints:
~ @ [] \ | { } § ł
In addition, keycodes in the range of 0xA5-DF are reserved for internal use:
Key Aliases Description
KC_NO XXXXXXX Ignore this key (NOOP)
KC_TRANSPARENT KC_TRNS, _______ Use the next lowest non-transparent key
* DENOTES SELECTED
Key Aliases Description
*KC_ENTER KC_ENT Return (Enter)
*KC_ESCAPE KC_ESC Escape
*KC_BSPACE KC_BSPC Delete (Backspace)
*KC_TAB Tab
*KC_SPACE KC_SPC Spacebar
*KC_MINUS KC_MINS - and _
*KC_EQUAL KC_EQL = and +
*KC_LBRACKET KC_LBRC [ and {
*KC_RBRACKET KC_RBRC ] and }
KC_BSLASH KC_BSLS \ and |
KC_NONUS_HASH KC_NUHS Non-US # and ~
KC_SCOLON KC_SCLN ; and :
*KC_QUOTE KC_QUOT ' and "
*KC_GRAVE KC_GRV, KC_ZKHK ` and ~, JIS Zenkaku/Hankaku
*KC_COMMA KC_COMM , and <
*KC_DOT . and >
KC_SLASH KC_SLSH / and ?
KC_NONUS_BSLASH KC_NUBS Non-US \ and |
Lock Keys
Key Aliases Description
*KC_CAPSLOCK KC_CLCK, KC_CAPS Caps Lock
KC_SCROLLLOCK KC_SLCK, KC_BRMD Scroll Lock, Brightness Down (macOS)
KC_NUMLOCK KC_NLCK Keypad Num Lock and Clear
KC_LOCKING_CAPS KC_LCAP Locking Caps Lock
KC_LOCKING_NUM KC_LNUM Locking Num Lock
KC_LOCKING_SCROLL KC_LSCR Locking Scroll Lock
Modifiers
Key Aliases Description
*KC_LCTRL KC_LCTL Left Control
*KC_LSHIFT KC_LSFT Left Shift
*KC_LALT KC_LOPT Left Alt (Option)
*KC_LGUI KC_LCMD, KC_LWIN Left GUI (Windows/Command/Meta key)
KC_RCTRL KC_RCTL Right Control
KC_RSHIFT KC_RSFT Right Shift
KC_RALT KC_ROPT, KC_ALGR Right Alt (Option/AltGr)
KC_RGUI KC_RCMD, KC_RWIN Right GUI (Windows/Command/Meta key)
Commands
Key Aliases Description
*KC_PSCREEN KC_PSCR Print Screen
KC_PAUSE KC_PAUS, KC_BRK, KC_BRMU Pause, Brightness Up (macOS)
KC_INSERT KC_INS Insert
KC_HOME Home
KC_PGUP Page Up
*KC_DELETE KC_DEL Forward Delete
KC_END End
KC_PGDOWN KC_PGDN Page Down
*KC_RIGHT KC_RGHT Right Arrow
*KC_LEFT Left Arrow
*KC_DOWN Down Arrow
*KC_UP Up Arrow
KC_APPLICATION KC_APP Application (Windows Context Menu Key)
KC_POWER System Power
KC_EXECUTE KC_EXEC Execute
KC_HELP Help
KC_MENU Menu
KC_SELECT KC_SLCT Select
KC_STOP Stop
KC_AGAIN KC_AGIN Again
KC_UNDO Undo
KC_CUT Cut
KC_COPY Copy
KC_PASTE KC_PSTE Paste
KC_FIND Find
KC__MUTE Mute
KC__VOLUP Volume Up
KC__VOLDOWN Volume Down
KC_ALT_ERASE KC_ERAS Alternate Erase
KC_SYSREQ SysReq/Attention
KC_CANCEL Cancel
KC_CLEAR KC_CLR Clear
KC_PRIOR Prior
KC_RETURN Return
KC_SEPARATOR Separator
KC_OUT Out
KC_OPER Oper
KC_CLEAR_AGAIN Clear/Again
KC_CRSEL CrSel/Props
KC_EXSEL ExSel
**/

View File

@ -0,0 +1 @@
# The default keymap for BALTHAZAR

View File

@ -0,0 +1,159 @@
/*
BALTHAZAR 2020 turbo
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, either version 2 of the License, or
(at your option) any later version.
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 QMK_KEYBOARD_H
/*
we have left and right split 7 cols
per each split col we have 11 rows
all 77 matrix nodes are used
we could add another row
we could add another row or rather col
Programming usage is our focus:
Esc is ok, Tab is ok
Left Shift key is important - switches between:
- numbers and ¨ ! " # $ % & / ( ) = ? *
- small letters and their capitals
- < and > ...
Cap is of secondary importance
Ctrl and Alt are ok
GUI is important - switches between views
Right Shift key (KC_RSFT) can be used for something else AltGr -> KC_RALT or KC_ROPT or KC_ALGR
In the middle F6 and F7 act as mouse left and right buttons - above is touchpad
to the far left and right are loudspeakers
* rows are verticals
* 1 2 3 4 5 6 7 1 2 3 4 5 6 7
*
* EscF1 F2 F3 F4 F5 F6 F7 F8 F9 F10F11F12PScr
*
* Tab `  1  2  3  4  5  6  7  8  9  0  -  = Del
*
* ShftCap Q  W  E  R  T  Y  U  I  O  P  [  ] Back
*
* CtrlAlt A  S  D  F  G  H  J  K  L  ;  '  # Entr
*
* GUI \  Z  X  C  V  B  N  M  ,  .  / UP AltG
*
* SpcSpc  Spc                Spc  LFTDWNRGHT
* space keys are four parallel keys
*
* 7x11 = 7 rows scanning + 11 cols reading
*
* row 1 = Esc, Grave, Tab, Caps, Shift, Ctrl, N, J, U, 7, F1
* row 2 = F1, 1, Q, A, Nubs, Alt, M, K, I, 8, F8
* etc.
*/
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = { // 7x11 ISO
{ KC_ESC, KC_GRV, KC_TAB, KC_CAPS, KC_LSFT, KC_LCTL, KC_N, KC_J, KC_U, KC_7, KC_F7 },
{ KC_F1, KC_1, KC_Q, KC_A, KC_NUBS, KC_LALT, KC_M, KC_K, KC_I, KC_8, KC_F8 },
{ KC_F2, KC_2, KC_W, KC_S, KC_Z, KC_LGUI, KC_COMM, KC_L, KC_O, KC_9, KC_F9 },
{ KC_F3, KC_3, KC_E, KC_D, KC_X, KC_SPC, KC_DOT, KC_SCLN, KC_P, KC_0, KC_F10 },
{ KC_F4, KC_4, KC_R, KC_F, KC_C, KC_LEFT, KC_SLSH, KC_QUOT, KC_LBRC, KC_MINS, KC_F11 },
{ KC_F5, KC_5, KC_T, KC_G, KC_V, KC_DOWN, KC_UP, KC_NUHS, KC_RBRC, KC_EQL, KC_F12 },
{ KC_F6, KC_6, KC_Y, KC_H, KC_B, KC_RIGHT, KC_ALGR, KC_ENT, KC_BSPC, KC_DEL, KC_PSCR },
},
[1] = { // 7x11 ISO mouse layer
{ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_MS_BTN2 },
{ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ },
{ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ },
{ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ },
{ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ },
{ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ },
{ KC_MS_BTN1, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ },
},
};
// Movement Hook
// Process mouse movement in the keymap before it is sent to the host. Example uses include filtering noise, adding acceleration, and automatically activating a layer.
void ps2_mouse_moved_user(report_mouse_t *mouse_report){
// here we have sensed the movement and need to activate layer index 1
layer_on(1);
}
/*
* We want to have F6 and F7 keys become Left and Right trackpad (mouse) buttons when cursor movement detected
* number 6 KC_6 can be middle scrolling activator - when pushed and trackpad movement detected - scroll screen instead of cursor move
* this is done with additional layer having so-called transparent keys everywhere but on the L anad R mouse keys
* Valid ways to denote transparency on a given layer:
KC_TRANSPARENT
KC_TRNS (alias)
_______ (alias)
KC_MS_BTN1 KC_BTN1 Mouse Button 1
KC_MS_BTN2 KC_BTN2 Mouse Button 2
KC_MS_BTN3 KC_BTN3 Mouse Button 3 // should be middle button
**/
/**
Advanced option is keyboard as midi controller / step sequencer
https://docs.qmk.fm/#/feature_sequencer
Add the following line to your rules.mk:
SEQUENCER_ENABLE = yes
By default the sequencer has 16 steps, but you can override this setting in your config.h:
#define SEQUENCER_STEPS 32
Resolutions
While the tempo defines the absolute speed at which the sequencer goes through the steps, the resolution defines the granularity of these steps (from coarser to finer).
Resolution Description
SQ_RES_2 Every other beat
SQ_RES_2T Every 1.5 beats
SQ_RES_4 Every beat
SQ_RES_4T Three times per 2 beats
SQ_RES_8 Twice per beat
SQ_RES_8T Three times per beat
SQ_RES_16 Four times per beat
SQ_RES_16T Six times per beat
SQ_RES_32 Eight times per beat
Keycodes
Keycode Description
SQ_ON Start the step sequencer
SQ_OFF Stop the step sequencer
SQ_TOG Toggle the step sequencer playback
SQ_SALL Enable all the steps
SQ_SCLR Disable all the steps
SQ_S(n) Toggle the step n
SQ_TMPD Decrease the tempo
SQ_TMPU Increase the tempo
SQ_R(n) Set the resolution to n
SQ_RESD Change to the slower resolution
SQ_RESU Change to the faster resolution
SQ_T(n) Set n as the only active track or deactivate all
**/

View File

@ -0,0 +1 @@
# The turbo keymap for BALTHAZAR

View File

@ -0,0 +1,19 @@
/*
Copyright 2024 g1smo
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, either version 2 of the License, or
(at your option) any later version.
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/>.
*/
#pragma once
//#define OLED_FONT_H "glcdfont.c"

View File

@ -0,0 +1,247 @@
/*
Copyright 2024 g1smo
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, either version 2 of the License, or
(at your option) any later version.
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/>.
*/
// Helidox 8x6 font with Balthazar logo
#include "progmem.h"
static unsigned char const font[] PROGMEM = {
0x07, 0x08, 0x7F, 0x08, 0x07, 0x00,
0x3E, 0x5B, 0x4F, 0x5B, 0x3E, 0x00,
0x3E, 0x6B, 0x4F, 0x6B, 0x3E, 0x00,
0x1C, 0x3E, 0x7C, 0x3E, 0x1C, 0x00,
0x18, 0x3C, 0x7E, 0x3C, 0x18, 0x00,
0x1C, 0x57, 0x7D, 0x57, 0x1C, 0x00,
0x1C, 0x5E, 0x7F, 0x5E, 0x1C, 0x00,
0x00, 0x18, 0x3C, 0x18, 0x00, 0x00,
0xFF, 0xE7, 0xC3, 0xE7, 0xFF, 0x00,
0x00, 0x18, 0x24, 0x18, 0x00, 0x00,
0xFF, 0xE7, 0xDB, 0xE7, 0xFF, 0x00,
0x30, 0x48, 0x3A, 0x06, 0x0E, 0x00,
0x26, 0x29, 0x79, 0x29, 0x26, 0x00,
0x40, 0x7F, 0x05, 0x05, 0x07, 0x00,
0x40, 0x7F, 0x05, 0x25, 0x3F, 0x00,
0x5A, 0x3C, 0xE7, 0x3C, 0x5A, 0x00,
0x7F, 0x3E, 0x1C, 0x1C, 0x08, 0x00,
0x08, 0x1C, 0x1C, 0x3E, 0x7F, 0x00,
0x14, 0x22, 0x7F, 0x22, 0x14, 0x00,
0x5F, 0x5F, 0x00, 0x5F, 0x5F, 0x00,
0x06, 0x09, 0x7F, 0x01, 0x7F, 0x00,
0x00, 0x66, 0x89, 0x95, 0x6A, 0x00,
0x60, 0x60, 0x60, 0x60, 0x60, 0x00,
0x94, 0xA2, 0xFF, 0xA2, 0x94, 0x00,
0x08, 0x04, 0x7E, 0x04, 0x08, 0x00,
0x10, 0x20, 0x7E, 0x20, 0x10, 0x00,
0x08, 0x08, 0x2A, 0x1C, 0x08, 0x00,
0x08, 0x1C, 0x2A, 0x08, 0x08, 0x00,
0x1E, 0x10, 0x10, 0x10, 0x10, 0x00,
0x0C, 0x1E, 0x0C, 0x1E, 0x0C, 0x00,
0x30, 0x38, 0x3E, 0x38, 0x30, 0x00,
0x06, 0x0E, 0x3E, 0x0E, 0x06, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x5F, 0x00, 0x00, 0x00,
0x00, 0x07, 0x00, 0x07, 0x00, 0x00,
0x14, 0x7F, 0x14, 0x7F, 0x14, 0x00,
0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x00,
0x23, 0x13, 0x08, 0x64, 0x62, 0x00,
0x36, 0x49, 0x56, 0x20, 0x50, 0x00,
0x00, 0x08, 0x07, 0x03, 0x00, 0x00,
0x00, 0x1C, 0x22, 0x41, 0x00, 0x00,
0x00, 0x41, 0x22, 0x1C, 0x00, 0x00,
0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 0x00,
0x08, 0x08, 0x3E, 0x08, 0x08, 0x00,
0x00, 0x80, 0x70, 0x30, 0x00, 0x00,
0x08, 0x08, 0x08, 0x08, 0x08, 0x00,
0x00, 0x00, 0x60, 0x60, 0x00, 0x00,
0x20, 0x10, 0x08, 0x04, 0x02, 0x00,
0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00,
0x00, 0x42, 0x7F, 0x40, 0x00, 0x00,
0x72, 0x49, 0x49, 0x49, 0x46, 0x00,
0x21, 0x41, 0x49, 0x4D, 0x33, 0x00,
0x18, 0x14, 0x12, 0x7F, 0x10, 0x00,
0x27, 0x45, 0x45, 0x45, 0x39, 0x00,
0x3C, 0x4A, 0x49, 0x49, 0x31, 0x00,
0x41, 0x21, 0x11, 0x09, 0x07, 0x00,
0x36, 0x49, 0x49, 0x49, 0x36, 0x00,
0x46, 0x49, 0x49, 0x29, 0x1E, 0x00,
0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
0x00, 0x40, 0x34, 0x00, 0x00, 0x00,
0x00, 0x08, 0x14, 0x22, 0x41, 0x00,
0x14, 0x14, 0x14, 0x14, 0x14, 0x00,
0x00, 0x41, 0x22, 0x14, 0x08, 0x00,
0x02, 0x01, 0x59, 0x09, 0x06, 0x00,
0x3E, 0x41, 0x5D, 0x59, 0x4E, 0x00,
0x7C, 0x12, 0x11, 0x12, 0x7C, 0x00,
0x7F, 0x49, 0x49, 0x49, 0x36, 0x00,
0x3E, 0x41, 0x41, 0x41, 0x22, 0x00,
0x7F, 0x41, 0x41, 0x41, 0x3E, 0x00,
0x7F, 0x49, 0x49, 0x49, 0x41, 0x00,
0x7F, 0x09, 0x09, 0x09, 0x01, 0x00,
0x3E, 0x41, 0x41, 0x51, 0x73, 0x00,
0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00,
0x00, 0x41, 0x7F, 0x41, 0x00, 0x00,
0x20, 0x40, 0x41, 0x3F, 0x01, 0x00,
0x7F, 0x08, 0x14, 0x22, 0x41, 0x00,
0x7F, 0x40, 0x40, 0x40, 0x40, 0x00,
0x7F, 0x02, 0x1C, 0x02, 0x7F, 0x00,
0x7F, 0x04, 0x08, 0x10, 0x7F, 0x00,
0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00,
0x7F, 0x09, 0x09, 0x09, 0x06, 0x00,
0x3E, 0x41, 0x51, 0x21, 0x5E, 0x00,
0x7F, 0x09, 0x19, 0x29, 0x46, 0x00,
0x26, 0x49, 0x49, 0x49, 0x32, 0x00,
0x03, 0x01, 0x7F, 0x01, 0x03, 0x00,
0x3F, 0x40, 0x40, 0x40, 0x3F, 0x00,
0x1F, 0x20, 0x40, 0x20, 0x1F, 0x00,
0x3F, 0x40, 0x38, 0x40, 0x3F, 0x00,
0x63, 0x14, 0x08, 0x14, 0x63, 0x00,
0x03, 0x04, 0x78, 0x04, 0x03, 0x00,
0x61, 0x59, 0x49, 0x4D, 0x43, 0x00,
0x00, 0x7F, 0x41, 0x41, 0x41, 0x00,
0x02, 0x04, 0x08, 0x10, 0x20, 0x00,
0x00, 0x41, 0x41, 0x41, 0x7F, 0x00,
0x04, 0x02, 0x01, 0x02, 0x04, 0x00,
0x40, 0x40, 0x40, 0x40, 0x40, 0x00,
0x00, 0x03, 0x07, 0x08, 0x00, 0x00,
0x20, 0x54, 0x54, 0x78, 0x40, 0x00,
0x7F, 0x28, 0x44, 0x44, 0x38, 0x00,
0x38, 0x44, 0x44, 0x44, 0x28, 0x00,
0x38, 0x44, 0x44, 0x28, 0x7F, 0x00,
0x38, 0x54, 0x54, 0x54, 0x18, 0x00,
0x00, 0x08, 0x7E, 0x09, 0x02, 0x00,
0x18, 0xA4, 0xA4, 0x9C, 0x78, 0x00,
0x7F, 0x08, 0x04, 0x04, 0x78, 0x00,
0x00, 0x44, 0x7D, 0x40, 0x00, 0x00,
0x20, 0x40, 0x40, 0x3D, 0x00, 0x00,
0x7F, 0x10, 0x28, 0x44, 0x00, 0x00,
0x00, 0x41, 0x7F, 0x40, 0x00, 0x00,
0x7C, 0x04, 0x78, 0x04, 0x78, 0x00,
0x7C, 0x08, 0x04, 0x04, 0x78, 0x00,
0x38, 0x44, 0x44, 0x44, 0x38, 0x00,
0xFC, 0x18, 0x24, 0x24, 0x18, 0x00,
0x18, 0x24, 0x24, 0x18, 0xFC, 0x00,
0x7C, 0x08, 0x04, 0x04, 0x08, 0x00,
0x48, 0x54, 0x54, 0x54, 0x24, 0x00,
0x04, 0x04, 0x3F, 0x44, 0x24, 0x00,
0x3C, 0x40, 0x40, 0x20, 0x7C, 0x00,
0x1C, 0x20, 0x40, 0x20, 0x1C, 0x00,
0x3C, 0x40, 0x30, 0x40, 0x3C, 0x00,
0x44, 0x28, 0x10, 0x28, 0x44, 0x00,
0x4C, 0x90, 0x90, 0x90, 0x7C, 0x00,
0x44, 0x64, 0x54, 0x4C, 0x44, 0x00,
0x00, 0x08, 0x36, 0x41, 0x00, 0x00,
0x00, 0x00, 0x77, 0x00, 0x00, 0x00,
0x00, 0x41, 0x36, 0x08, 0x00, 0x00,
0x02, 0x01, 0x02, 0x04, 0x02, 0x00,
0x3C, 0x26, 0x23, 0x26, 0x3C, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x30, 0x78, 0x48, 0xD8, 0xF0,
0xE0, 0x84, 0x86, 0xFF, 0xFF, 0x86,
0x84, 0xC0, 0xF0, 0xD8, 0x48, 0x78,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xE0, 0xF0, 0xF0,
0x30, 0x30, 0x30, 0x70, 0xE0, 0xC0,
0x00, 0x00, 0x00, 0x00, 0xC0, 0xF0,
0xF0, 0xF0, 0xC0, 0x00, 0x00, 0x00,
0x00, 0xE0, 0xF0, 0xE0, 0x00, 0x00,
0x00, 0x30, 0x30, 0x30, 0xF0, 0xF0,
0xF0, 0x30, 0x30, 0x30, 0x00, 0xF0,
0xF0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00,
0x00, 0x00, 0xE0, 0xF0, 0xF0, 0xE0,
0x80, 0x00, 0x00, 0x00, 0x30, 0x30,
0x30, 0x30, 0x30, 0xF0, 0xF0, 0x70,
0x00, 0x00, 0x00, 0x00, 0xE0, 0xF0,
0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00,
0x00, 0xF0, 0xF0, 0x30, 0x30, 0x30,
0x30, 0xE0, 0xE0, 0x80, 0x00, 0x00,
0x00, 0xC0, 0xF0, 0xF8, 0xFC, 0x3E,
0x1E, 0x06, 0x01, 0x00, 0x00, 0x00,
0x7F, 0x41, 0x41, 0x41, 0x7F, 0x00,
0x7F, 0x41, 0x41, 0x41, 0x7F, 0x00,
0x00, 0x80, 0xC0, 0xE0, 0x7E, 0x5B,
0x4F, 0x5B, 0xFE, 0xC0, 0x00, 0x00,
0xC0, 0x00, 0xDC, 0xD7, 0xDE, 0xDE,
0xDE, 0xD7, 0xDC, 0x00, 0xC0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0x1C,
0x3E, 0x08, 0x08, 0x08, 0x88, 0xFF,
0xFF, 0xC9, 0xC9, 0xFF, 0xFF, 0xC9,
0xC9, 0xFF, 0xFF, 0x88, 0x08, 0x08,
0x08, 0x3E, 0x1C, 0x08, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
0x0C, 0x0C, 0x0C, 0x1E, 0xFF, 0xF1,
0x00, 0x00, 0xE0, 0xFE, 0x7F, 0x63,
0x60, 0x67, 0x7F, 0xFC, 0xE0, 0x00,
0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF,
0xFF, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
0x0C, 0xFF, 0xFF, 0x00, 0x00, 0xC0,
0xF8, 0xFF, 0x6F, 0x61, 0x61, 0x6F,
0xFF, 0xF8, 0xC0, 0x00, 0x80, 0xE0,
0xF0, 0x3C, 0x0F, 0x07, 0x01, 0x00,
0x00, 0xC0, 0xF8, 0xFF, 0x6F, 0x60,
0x61, 0x6F, 0xFF, 0xF8, 0xC0, 0x00,
0x00, 0xFF, 0xFF, 0x0C, 0x08, 0x3C,
0xFC, 0xEF, 0x87, 0x03, 0x00, 0x00,
0x00, 0x03, 0x0F, 0x1F, 0x3F, 0x3C,
0x78, 0x70, 0x60, 0x00, 0x00, 0x00,
0x7F, 0x41, 0x41, 0x41, 0x7F, 0x00,
0x7F, 0x41, 0x41, 0x41, 0x7F, 0x00,
0x30, 0x7B, 0x7F, 0x78, 0x30, 0x20,
0x20, 0x30, 0x78, 0x7F, 0x3B, 0x00,
0x03, 0x00, 0x0F, 0x7F, 0x0F, 0x0F,
0x0F, 0x7F, 0x0F, 0x00, 0x03, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x06, 0x0F, 0x09, 0x0D, 0x07,
0x01, 0x10, 0x30, 0x7F, 0x7F, 0x30,
0x10, 0x01, 0x07, 0x0D, 0x09, 0x0F,
0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x07, 0x07,
0x06, 0x06, 0x02, 0x03, 0x03, 0x01,
0x00, 0x03, 0x07, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x07, 0x02,
0x00, 0x03, 0x07, 0x07, 0x06, 0x06,
0x06, 0x06, 0x00, 0x00, 0x03, 0x07,
0x03, 0x00, 0x00, 0x00, 0x00, 0x03,
0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0x03, 0x00, 0x00, 0x07,
0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0x07, 0x02, 0x03, 0x07,
0x07, 0x06, 0x06, 0x06, 0x06, 0x02,
0x02, 0x07, 0x03, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x07, 0x00,
0x00, 0x03, 0x03, 0x00, 0x00, 0x00,
0x00, 0x03, 0x07, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

View File

@ -0,0 +1,189 @@
/*
BALTHAZAR 2020 turbo
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, either version 2 of the License, or
(at your option) any later version.
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 QMK_KEYBOARD_H
#include "oled.c"
/*
we have left and right split 7 cols
per each split col we have 11 rows
all 77 matrix nodes are used
we could add another row
we could add another row or rather col
Programming usage is our focus:
Esc is ok, Tab is ok
Left Shift key is important - switches between:
- numbers and ¨ ! " # $ % & / ( ) = ? *
- small letters and their capitals
- < and > ...
Cap is of secondary importance
Ctrl and Alt are ok
GUI is important - switches between views
Right Shift key (KC_RSFT) can be used for something else AltGr -> KC_RALT or KC_ROPT or KC_ALGR
In the middle F6 and F7 act as mouse left and right buttons - above is touchpad
to the far left and right are loudspeakers
* rows are verticals
* 1 2 3 4 5 6 7 1 2 3 4 5 6 7
*
* EscF1 F2 F3 F4 F5 F6 F7 F8 F9 F10F11F12PScr
*
* Tab `  1  2  3  4  5  6  7  8  9  0  -  = Del
*
* ShftCap Q  W  E  R  T  Y  U  I  O  P  [  ] Back
*
* CtrlAlt A  S  D  F  G  H  J  K  L  ;  '  # Entr
*
* GUI \  Z  X  C  V  B  N  M  ,  .  / UP AltG
*
* SpcSpc  Spc                Spc  LFTDWNRGHT
* space keys are four parallel keys
*
* 7x11 = 7 rows scanning + 11 cols reading
*
* row 1 = Esc, Grave, Tab, Caps, Shift, Ctrl, N, J, U, 7, F1
* row 2 = F1, 1, Q, A, Nubs, Alt, M, K, I, 8, F8
* etc.
*/
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = { // 7x11 ISO
{ KC_ESC, KC_GRV, KC_TAB, KC_CAPS, KC_LSFT, KC_LCTL, KC_N, KC_J, KC_U, KC_7, KC_F7 },
{ KC_F1, KC_1, KC_Q, KC_A, KC_NUBS, KC_LALT, KC_M, KC_K, KC_I, KC_8, KC_F8 },
{ KC_F2, KC_2, KC_W, KC_S, KC_Z, KC_LGUI, KC_COMM, KC_L, KC_O, KC_9, KC_F9 },
{ KC_F3, KC_3, KC_E, KC_D, KC_X, KC_SPC, KC_DOT, KC_SCLN, KC_P, KC_0, KC_F10 },
{ KC_F4, KC_4, KC_R, KC_F, KC_C, KC_LEFT, KC_SLSH, KC_QUOT, KC_LBRC, KC_MINS, KC_F11 },
{ KC_F5, KC_5, KC_T, KC_G, KC_V, KC_DOWN, KC_UP, KC_NUHS, KC_RBRC, KC_EQL, KC_F12 },
{ KC_F6, KC_6, KC_Y, KC_H, KC_B, KC_RIGHT, KC_ALGR, KC_ENT, KC_BSPC, KC_DEL, KC_PSCR },
},
[1] = { // 7x11 ISO mouse layer
{ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_MS_BTN2 },
{ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ },
{ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ },
{ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ },
{ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ },
{ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ },
{ KC_MS_BTN1, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ },
},
};
// Movement Hook
// Process mouse movement in the keymap before it is sent to the host. Example uses include filtering noise, adding acceleration, and automatically activating a layer.
void ps2_mouse_moved_user(report_mouse_t *mouse_report){
// here we have sensed the movement and need to activate layer index 1
layer_on(1);
}
/*
* We want to have F6 and F7 keys become Left and Right trackpad (mouse) buttons when cursor movement detected
* number 6 KC_6 can be middle scrolling activator - when pushed and trackpad movement detected - scroll screen instead of cursor move
* this is done with additional layer having so-called transparent keys everywhere but on the L anad R mouse keys
* Valid ways to denote transparency on a given layer:
KC_TRANSPARENT
KC_TRNS (alias)
_______ (alias)
KC_MS_BTN1 KC_BTN1 Mouse Button 1
KC_MS_BTN2 KC_BTN2 Mouse Button 2
KC_MS_BTN3 KC_BTN3 Mouse Button 3 // should be middle button
**/
/**
// oled - this assumes we have layers defined and named indirectly
#ifdef OLED_ENABLE
void oled_task_user(void) {
// Host Keyboard Layer Status
oled_write_P(PSTR("Layer: "), false);
// get_highest_layer should return indexes 0, 1, 2
switch (get_highest_layer(layer_state)) {
case _QWERTY:
oled_write_P(PSTR("Default\n"), false);
break;
case _FN:
oled_write_P(PSTR("FN\n"), false);
break;
case _ADJ:
oled_write_P(PSTR("ADJ\n"), false);
break;
default:
// Or use the write_ln shortcut over adding '\n' to the end of your string
oled_write_ln_P(PSTR("Undefined"), false);
}
// Host Keyboard LED Status
led_t led_state = host_keyboard_led_state();
oled_write_P(led_state.num_lock ? PSTR("NUM ") : PSTR(" "), false);
oled_write_P(led_state.caps_lock ? PSTR("CAP ") : PSTR(" "), false);
oled_write_P(led_state.scroll_lock ? PSTR("SCR ") : PSTR(" "), false);
}
#endif
**/
/**
Advanced option is keyboard as midi controller / step sequencer
https://docs.qmk.fm/#/feature_sequencer
Add the following line to your rules.mk:
SEQUENCER_ENABLE = yes
By default the sequencer has 16 steps, but you can override this setting in your config.h:
#define SEQUENCER_STEPS 32
Resolutions
While the tempo defines the absolute speed at which the sequencer goes through the steps, the resolution defines the granularity of these steps (from coarser to finer).
Resolution Description
SQ_RES_2 Every other beat
SQ_RES_2T Every 1.5 beats
SQ_RES_4 Every beat
SQ_RES_4T Three times per 2 beats
SQ_RES_8 Twice per beat
SQ_RES_8T Three times per beat
SQ_RES_16 Four times per beat
SQ_RES_16T Six times per beat
SQ_RES_32 Eight times per beat
Keycodes
Keycode Description
SQ_ON Start the step sequencer
SQ_OFF Stop the step sequencer
SQ_TOG Toggle the step sequencer playback
SQ_SALL Enable all the steps
SQ_SCLR Disable all the steps
SQ_S(n) Toggle the step n
SQ_TMPD Decrease the tempo
SQ_TMPU Increase the tempo
SQ_R(n) Set the resolution to n
SQ_RESD Change to the slower resolution
SQ_RESU Change to the faster resolution
SQ_T(n) Set n as the only active track or deactivate all
**/

View File

@ -0,0 +1,236 @@
/*
Copyright 2024 Jurij Podgoršek <jurij@kompot.si>
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, either version 3 of the License, or
(at your option) any later version.
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/>.
*/
#ifdef OLED_ENABLE
#define PASSWORD_MAX_LEN 128
/*
static void print_status(void) {
// Host Keyboard LED Status
led_t led_state = host_keyboard_led_state();
oled_write_P(led_state.num_lock ? PSTR("NUM ") : PSTR(" "), false);
oled_write_P(led_state.caps_lock ? PSTR("CAP ") : PSTR(" "), false);
oled_write_P(led_state.scroll_lock ? PSTR("SCR ") : PSTR(" "), false);
}
*/
char entryBuffer[PASSWORD_MAX_LEN] = {};
int entryBufferIndex = 0;
// Print password (using * to conceal password)
void printEntryBufferR(char replaceChar) {
for (int i = 0; i < sizeof entryBuffer; i++) {
if (entryBuffer[i] != '\0') {
if (replaceChar == '\0') {
oled_write_char(entryBuffer[i], false);
} else {
oled_write_char('*', false);
}
}
}
}
void printEntryBuffer(void) {
printEntryBufferR('\0');
}
void clearEntryBuffer(void) {
memset(entryBuffer, 0, sizeof entryBuffer);
}
// Show logo (in custom font)
static void render_logo(void) {
static const char PROGMEM balthazar_logo[] = {
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94,
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4,
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0x00
};
oled_write_P(balthazar_logo, false);
}
// Possible states
enum boot_state {
STATE_SPLASH = 0,
STATE_PASSWORD_SET = 10,
STATE_PASSWORD_SET_SUCCESS = 15,
STATE_PASSWORD_ENTER = 20,
STATE_PASSWORD_INVALID = 25,
STATE_BOOT_MENU = 30,
STATE_STARTING = 40
};
static uint16_t state_timer;
enum boot_state current_state = STATE_SPLASH;
oled_rotation_t oled_init_kb(oled_rotation_t rotation) {
return rotation;
}
oled_rotation_t oled_init_user(oled_rotation_t rotation) {
// Timer to show logo on start
state_timer = timer_read();
return rotation;
}
void progress_state(void) {
switch (current_state) {
case STATE_SPLASH:
oled_clear();
// @TODO check if pw set!
current_state = STATE_PASSWORD_SET;
break;
case STATE_PASSWORD_ENTER:
// @TODO Check if pw ok!
if (true) {
current_state = STATE_BOOT_MENU;
} else {
current_state = STATE_PASSWORD_INVALID;
}
break;
case STATE_PASSWORD_INVALID:
current_state = STATE_PASSWORD_ENTER;
break;
case STATE_PASSWORD_SET:
// @TODO save to EEPROM
oled_clear();
clearEntryBuffer();
current_state = STATE_PASSWORD_SET_SUCCESS;
break;
case STATE_PASSWORD_SET_SUCCESS:
//current_state = STATE_BOOT_MENU;
current_state = STATE_PASSWORD_SET;
break;
case STATE_BOOT_MENU:
current_state = STATE_STARTING;
break;
case STATE_STARTING:
// TODO actual boot!
break;
}
state_timer = timer_read();
}
const int TRANSITION_TIME = 3000;
bool state_confirm = false;
bool oled_task_user(void) {
switch (current_state) {
// Show splash for 3 seconds
case STATE_SPLASH:
render_logo();
oled_write_P(PSTR("Open hardware laptop"), false);
if (timer_elapsed(state_timer) > TRANSITION_TIME) {
progress_state();
}
break;
case STATE_PASSWORD_ENTER:
render_logo();
oled_write_ln_P(PSTR("Enter password:"), false);
// @TODO capture input, compare with EEPROM
break;
case STATE_PASSWORD_SET:
oled_write_ln_P(PSTR("No password found."), false);
oled_write_ln_P(PSTR("Set new password:"), false);
printEntryBufferR('*');
// @TODO capture input, save to EEPROM
break;
case STATE_PASSWORD_SET_SUCCESS:
//render_logo();
oled_clear();
oled_write_ln_P(PSTR("Password set success!"), false);
printEntryBuffer();
if (timer_elapsed(state_timer) > TRANSITION_TIME) {
progress_state();
}
break;
case STATE_PASSWORD_INVALID:
render_logo();
oled_write_P(PSTR("Invalid password. Try again"), false);
if (timer_elapsed(state_timer) > TRANSITION_TIME) {
progress_state();
}
break;
case STATE_BOOT_MENU:
if (state_confirm) {
oled_write_P(PSTR("Choose boot option:"), false);
// @TODO list options, keyboard selection
progress_state();
}
break;
case STATE_STARTING:
oled_write_P(PSTR("Starting up."), false);
if (timer_elapsed(state_timer) % 3000 > 1000) {
oled_write_P(PSTR("."), false);
}
if (timer_elapsed(state_timer) % 3000 > 2000) {
oled_write_P(PSTR("."), false);
}
break;
}
return false;
}
const char code_to_name[60] = {
' ', ' ', ' ', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
'R', 'E', 'B', 'T', ' ', ' ', ' ', ' ', ' ', ' ',
' ', ';', '\'', ' ', ',', '.', '/', ' ', ' ', ' '};
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
// Capture input to buffer in certain states
if ((current_state == STATE_PASSWORD_ENTER
|| current_state == STATE_PASSWORD_SET)
&& record->event.pressed) {
// Backspace?
if (keycode == KC_BSPC && entryBufferIndex > 0) {
entryBuffer[entryBufferIndex] = '\0';
entryBufferIndex -= 1;
// Submit entry
} else if (keycode == KC_ENT || keycode == KC_T) {
progress_state();
// Save current character
} else if (keycode < 60) {
// @TODO broaden from lowercase chars and numbers
entryBuffer[entryBufferIndex] = code_to_name[keycode];
entryBufferIndex += 1;
}
return false;
}
return true;
}
#endif // end OLED_ENABLE

View File

@ -0,0 +1 @@
# The turbo keymap for BALTHAZAR

View File

@ -0,0 +1 @@
OLED_ENABLE = yes # enable optional small i2c OLED 128x32 S

View File

@ -0,0 +1,22 @@
# Balthazar
Open-hardware laptop computer modules description and concept.
These are electronic schematic modules as presented at https://balthazar.space/wiki/Balthazar with the main aim for team access. See the [main repository](https://github.com/balthazar-space/balthazar) for other designs.
# Balthazar QMK firmware
![balthazar](https://balthazar.space/wiki/Keyboard#/media/File:Key_solderedon.png)
A customizable 80% keyboard.
* Keyboard Maintainers: [Turbosavski](https://github.com/Turbosavski) & [g1smo](https://github.com/g1smo)
* Hardware Supported: BALTHAZAR KEYBOARD
* Hardware Availability:
Make example for this keyboard (after setting up your build environment):
make balthazar3:default
make balthazar3:turbo
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).

View File

@ -0,0 +1,67 @@
# MCU name
MCU = atmega32u4
# defaults
#F_CPU = 16000000
#ARCH = AVR8
#F_USB = $(F_CPU)
#OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
# Bootloader selection
# Teensy halfkay
# Pro Micro caterina
# Atmel DFU atmel-dfu
# LUFA DFU lufa-dfu
# QMK DFU qmk-dfu
# ATmega32A bootloadHID
# ATmega328P USBasp
#BOOTLOADER = atmel-dfu
BOOTLOADER = caterina
# promicro
#BOOTLOADER = lufa-dfu
#QMK maintains a fork of the LUFA DFU bootloader that additionally performs a simple matrix scan for exiting the bootloader
#and returning to the application, as well as flashing an LED/making a ticking noise
#BOOTLOADER = qmk-dfu
# Build Options
# change yes to no to disable
PS2_MOUSE_ENABLE = no # use ps/2 touchpad - not yet
MOUSEKEY_ENABLE = no # Mouse keys - we dont use buttons on mousepad, but on keyboard
#To use USART on the ATMega32u4, you have to use PD5 for clock and PD2 for data.
#If one of those are unavailable, you need to use interrupt version.
#PS2_USE_INT = yes # first we us this one
#PS2_USE_USART = yes # later we will use this one
MIDI_ENABLE = no # MIDI support - might be usefull - need to declare keymap layer
BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration
EXTRAKEY_ENABLE = no # Audio control and System control
CONSOLE_ENABLE = no # Console for debug
COMMAND_ENABLE = no # Commands for debug and configuration
# optional small i2c OLED 128x64 (see toucholed keymap)
OLED_ENABLE = no
# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
NKRO_ENABLE = no # USB Nkey Rollover
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality / -> #define BACKLIGHT_PIN B7 in config.h
RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
UNICODE_ENABLE = no # Unicode - mabye?
BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
AUDIO_ENABLE = no # Audio output on port C6
FAUXCLICKY_ENABLE = no # Use buzzer to emulate clicky switches
#ISSI_ENABLE = yes # If the I2C pullup resistors aren't installed this must be disabled
#WATCHDOG_ENABLE = yes # Resets keyboard if matrix_scan isn't run every 250ms
#CUSTOM_MATRIX # Allows replacing the standard matrix scanning routine with a custom one.
#DEBOUNCE_TYPE # Allows replacing the standard key debouncing routine with an alternative or custom one.
#WAIT_FOR_USB = yes #Forces the keyboard to wait for a USB connection to be established before it starts up
#NO_USB_STARTUP_CHECK = yes #Disables usb suspend check after keyboard startup. Usually the keyboard waits for the host to wake it up before any tasks are performed. This is useful for split keyboards as one half will not get a wakeup call but must send commands to the master.
# Link time optimization
LTO_ENABLE = yes

View File

@ -17,15 +17,22 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DACTYL_CONFIG_H
#define DACTYL_CONFIG_H
#pragma once
/* key matrix size
* At this time, "row" in the dactyl's code actually means "column" on the
* physical keyboard. It's confusing. I'm sorry. Blame Jack Humbert :P
*/
#define DIODE_DIRECTION COL2ROW
#define MATRIX_ROWS 12
#define MATRIX_COLS 6
#define COL_EXPANDED { false, false, false, false, false, false}
#define MATRIX_ONBOARD_ROW_PINS { F6, F7, B1, B3, B2, B6 }
#define MATRIX_ONBOARD_COL_PINS { D4, C6, D7, E6, B4, B5 }
#define EXPANDER_COL_REGISTER GPIOA
#define EXPANDER_ROW_REGISTER GPIOB
#define MATRIX_EXPANDER_COL_PINS {0, 1, 2, 3, 4, 5}
#define MATRIX_EXPANDER_ROW_PINS {0, 1, 2, 3, 4, 5}
#define MOUSEKEY_INTERVAL 15
#define MOUSEKEY_DELAY 0
@ -47,4 +54,5 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define USB_MAX_POWER_CONSUMPTION 500
#endif
#define OLED_DISPLAY_64X128
#define OLED_DISPLAY_HEIGHT 64

View File

@ -1,8 +1,8 @@
#include "daktil.h"
#include "i2cmaster.h"
#include "i2c_master.h"
bool i2c_initialized = 0;
//bool i2c_initialized = 0;
uint8_t mcp23018_status = 0x20;
void matrix_init_kb(void) {
@ -25,15 +25,16 @@ void matrix_init_kb(void) {
matrix_init_user();
}
/*
uint8_t init_mcp23018(void) {
mcp23018_status = 0x20;
// I2C subsystem
if (i2c_initialized == 0) {
if (! i2c_initialized) {
i2c_init(); // on pins D(1,0)
i2c_initialized = true;
_delay_ms(1000);
wait_ms(1000);
}
// set pin direction
@ -60,6 +61,7 @@ out:
return mcp23018_status;
}
*/
#ifdef SWAP_HANDS_ENABLE
__attribute__ ((weak))

View File

@ -1,10 +1,9 @@
#ifndef DAKTIL_H
#define DAKTIL_H
#pragma once
#include "quantum.h"
#include <stdint.h>
#include <stdbool.h>
#include "i2cmaster.h"
#include "i2c_master.h"
#include <util/delay.h>
#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
@ -22,10 +21,12 @@
#define GPIOB 0x13
#define OLATA 0x14 // output latch register
#define OLATB 0x15
#define I2C_TIMEOUT 100
extern uint8_t mcp23018_status;
void init_dactyl(void);
void init_expander(void);
uint8_t init_mcp23018(void);
#define KEYMAP( \
@ -68,5 +69,3 @@ uint8_t init_mcp23018(void);
#define LAYOUT_dactyl KEYMAP
#endif

View File

@ -10,7 +10,6 @@
},
"processor": "atmega32u4",
"bootloader": "caterina",
"diode_direction": "COL2ROW",
"features": {
"mousekey": true,
"extrakey": true,

View File

@ -203,3 +203,11 @@ void matrix_init_user(void) {
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {};
#ifdef OLED_ENABLE
bool oled_task_user(void) {
oled_write_P(PSTR("Keyboard:\n"), false);
oled_write_P(PSTR("BALTHAZAR"), false);
return false;
}
#endif

View File

@ -1,183 +0,0 @@
#include "daktil.h"
#include "debug.h"
#include "action_layer.h"
#include "version.h"
#define BASE 0 // default layer
#define SYMB 1 // symbols
#define MDIA 2 // media keys
enum custom_keycodes {
PLACEHOLDER = SAFE_RANGE, // ensure these codes start after the highest keycode defined in Quantum
VRSN,
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* Keymap 0: Basic layer
*
* ,-----------------------------------------. ,-----------------------------------------.
* | = | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | - |
* |------+------+------+------+------+------| |------+------+------+------+------+------|
* | Del | '" | , | . | P | Y | | F | G | C | R | L | \ |
* |------+------+------+------+------+------| |------+------+------+------+------+------|
* | BkSp | A | O | E | U | I | | D | H | T | N | S/L2 |//Cmd |
* |------+------+------+------+------+------| |------+------+------+------+------+------|
* |LShift|;/Ctrl| Q | J | K | X | | B | M | W | V |Z/Ctrl|RShift|
* |------+------+------+------+------+------' `------+------+------+------+------+------|
* |Grv/L1| = |AltShf| Left | Right| | Up | Down | [ | ] | ~L1 |
* `----------------------------------' `----------------------------------'
* ,-------------. ,-------------.
* | App | LGui | | Alt | ^/Esc|
* ,------|------|------| |------+------+------.
* | | | Home | | PgUp | | |
* | Space|Backsp|------| |------| Tab |Enter |
* | |ace | End | | PgDn | | |
* `--------------------' `--------------------'
*/
[BASE] = LAYOUT_dactyl( // layer 0 : default
// left hand
KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5,
KC_DELT, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y,
KC_BSPC, KC_A, KC_O, KC_E, KC_U, KC_I,
KC_LSFT, CTL_T(KC_SCLN), KC_Q, KC_J, KC_K, KC_X,
LT(SYMB,KC_GRV), KC_EQL, LALT(KC_LSFT), KC_LEFT, KC_RGHT,
ALT_T(KC_APP), KC_LGUI,
KC_HOME,
KC_SPC, KC_BSPC, KC_END,
// right hand
KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
KC_F, KC_G, KC_C, KC_R, KC_L, KC_BSLS,
KC_D, KC_H, KC_T, KC_N, LT(MDIA, KC_S), GUI_T(KC_SLSH),
KC_B, KC_M, KC_W, KC_V, CTL_T(KC_Z), KC_RSFT,
KC_UP, KC_DOWN, KC_LBRC, KC_RBRC, KC_FN1,
KC_RALT, CTL_T(KC_ESC),
KC_PGUP,
KC_PGDN, KC_TAB, KC_ENT
),
/* Keymap 1: Symbol Layer
*
* ,-----------------------------------------. ,-----------------------------------------.
* |Versn | F1 | F2 | F3 | F4 | F5 | | F6 | F7 | F8 | F9 | F10 | F11 |
* |------+------+------+------+------+------| |------+------+------+------+------+------|
* | | ! | @ | { | } | | | | Up | 7 | 8 | 9 | * | F12 |
* |------+------+------+------+------+------| |------+------+------+------+------+------|
* | | # | $ | ( | ) | ` | | Down | 4 | 5 | 6 | + | |
* |------+------+------+------+------+------| |------+------+------+------+------+------|
* | | % | ^ | [ | ] | ~ | | & | 1 | 2 | 3 | \ | |
* |------+------+------+------+------+------' `------+------+------+------+------+------|
* |RESET | | | | | | | . | 0 | = | |
* `----------------------------------' `----------------------------------'
* ,-------------. ,-------------.
* | | | | | |
* ,------|------|------| |------+------+------.
* | | | | | | | |
* | | |------| |------| | |
* | | | | | | | |
* `--------------------' `--------------------'
*/
// SYMBOLS
[SYMB] = LAYOUT_dactyl(
// left hand
VRSN, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5,
KC_TRNS, KC_EXLM, KC_AT, KC_LCBR, KC_RCBR, KC_PIPE,
KC_TRNS, KC_HASH, KC_DLR, KC_LPRN, KC_RPRN, KC_GRV,
KC_TRNS, KC_PERC, KC_CIRC, KC_LBRC, KC_RBRC, KC_TILD,
RESET, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS,
KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS,
// right hand
KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
KC_TRNS, KC_DOT, KC_0, KC_EQL, KC_TRNS,
KC_TRNS, KC_TRNS,
KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS
),
/* Keymap 2: Media and mouse keys
* ,-----------------------------------------. ,-----------------------------------------.
* | | | | | | | | | | | | | |
* |------+------+------+------+------+------| |------+------+------+------+------+------|
* | | | | MsUp | | | | | | | | | |
* |------+------+------+------+------+------| |------+------+------+------+------+------|
* | | |MsLeft|MsDown|MsRght| | | | | | | | Play |
* |------+------+------+------+------+------| |------+------+------+------+------+------|
* | | | | | | | | | | Prev | Next | | |
* |------+------+------+------+------+------' `------+------+------+------+------+------|
* | | | | Lclk | Rclk | | VolUp| VolDn| Mute | | |
* `----------------------------------' `----------------------------------'
* ,-------------. ,-------------.
* | | | | | |
* ,------|------|------| |------+------+------.
* | | | | | | |Brwser|
* | | |------| |------| |Back |
* | | | | | | | |
* `--------------------' `--------------------'
*
*/
// MEDIA AND MOUSE
[MDIA] = LAYOUT_dactyl(
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
KC_TRNS, KC_TRNS,
KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS,
// right hand
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS,
KC_TRNS,
KC_TRNS, KC_TRNS, KC_WBAK
),
};
const uint16_t PROGMEM fn_actions[] = {
[1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
};
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
{
// MACRODOWN only works in this function
switch(id) {
case 0:
if (record->event.pressed) {
SEND_STRING (QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION);
}
break;
case 1:
if (record->event.pressed) { // For resetting EEPROM
eeconfig_init();
}
break;
}
return MACRO_NONE;
};
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case VRSN:
if (record->event.pressed) {
SEND_STRING (QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION);
}
return false;
break;
}
return true;
}
// Runs just one time when the keyboard initializes.
void matrix_init_user(void) {
};
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {};

View File

@ -1,9 +0,0 @@
# Dactyl Dvorak keymap
Modifiers and layers 1+ are the same as in the default layout.
Only the layer-0 dvorak-relevant keys are different.
## Changelog
* Nov 2017:
* Copied and adapted from the default keymap.

View File

@ -1,162 +0,0 @@
#include "daktil.h"
#include "debug.h"
#include "action_layer.h"
#include "version.h"
#define BASE 0 // default layer
#define CONT 1 // control layer
#define QWER 2 // qwerty layer
enum custom_keycodes {
PLACEHOLDER = SAFE_RANGE, // ensure these codes start after the highest keycode defined in Quantum
COLON_EQ,
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* Keymap 0: Basic layer
*
* ,-----------------------------------------. ,-----------------------------------------.
* | Esc | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | \ |
* |------+------+------+------+------+------| |------+------+------+------+------+------|
* | Tab | '" | , | . | P | Y | | F | G | C | R | L | / |
* |------+------+------+------+------+------| |------+------+------+------+------+------|
* | := | A | O | E | U | I | | D | H | T | N | S | - |
* |------+------+------+------+------+------| |------+------+------+------+------+------|
* |LShift| ; | Q | J | K | X | | B | M | W | V | Z |RShift|
* |------+------+------+------+------+------' `------+------+------+------+------+------|
* | Home | ` | = | Left | Right| | Up | Down | [ | ] | End |
* `----------------------------------' `----------------------------------'
* ,-------------. ,-------------.
* | LCtl | LAlt | | RCtl | Ralt |
* ,------|------|------| |------+------+------.
* | | | L1 | | L1 | | |
* | Back |Delete|------| |------|Enter |Space |
* |Space | | LGui | | RGui | | |
* `--------------------' `--------------------'
*/
[BASE] = LAYOUT_dactyl( // layer 0 : default
// left hand
KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5,
KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y,
COLON_EQ, KC_A, KC_O, KC_E, KC_U, KC_I,
KC_LSFT, KC_SCLN, KC_Q, KC_J, KC_K, KC_X,
KC_HOME, KC_GRV, KC_EQL, KC_LEFT, KC_RGHT,
KC_LCTRL, KC_LALT,
MO(CONT),
KC_BSPC, KC_DEL, KC_LGUI,
// right hand
KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSLS,
KC_F, KC_G, KC_C, KC_R, KC_L, KC_SLSH,
KC_D, KC_H, KC_T, KC_N, KC_S, KC_MINS,
KC_B, KC_M, KC_W, KC_V, KC_Z, KC_RSFT,
KC_UP, KC_DOWN, KC_LBRC, KC_RBRC, KC_END,
KC_RALT, KC_RCTL,
MO(CONT),
KC_RGUI, KC_ENT, KC_SPACE
),
/* Keymap 1: Control layer (media keys, Fkeys, numpad)
*
* ,-----------------------------------------. ,-----------------------------------------.
* | | F1 | F2 | F3 | F4 | F5 | | F6 | F7 | F8 | F9 | F10 | RESET|
* |------+------+------+------+------+------| |------+------+------+------+------+------|
* | | | Mute | VolD | VolU | | | | 7 | 8 | 9 | + | |
* |------+------+------+------+------+------| |------+------+------+------+------+------|
* | | | Prev |PPause| Next | | | | 4 | 5 | 6 | = | |
* |------+------+------+------+------+------| |------+------+------+------+------+------|
* | | | | | | | | | 1 | 2 | 3 | , | |
* |------+------+------+------+------+------' `------+------+------+------+------+------|
* |PageUp| | | | | | 0 | 0 | . | |PageDn|
* `----------------------------------' `----------------------------------'
* ,-------------. ,-------------.
* | | | | | |
* ,------|------|------| |------+------+------.
* | | | | | | | |
* | | |------| |------| | |
* | | | | | | | |
* `--------------------' `--------------------'
*/
// SYMBOLS
[CONT] = LAYOUT_dactyl(
// left hand
KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5,
KC_TRNS, KC_TRNS, KC_MUTE, KC_VOLD, KC_VOLU, KC_TRNS,
TG(QWER), KC_TRNS, KC_MPRV, KC_MPLY, KC_MNXT, KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_PGUP, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS,
KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS,
// right hand
KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, RESET,
KC_TRNS, KC_7, KC_8, KC_9, KC_KP_PLUS, KC_TRNS,
KC_TRNS, KC_4, KC_5, KC_6, KC_EQL, KC_TRNS,
KC_TRNS, KC_1, KC_2, KC_3, KC_COMM, KC_TRNS,
KC_0, KC_0, KC_DOT, KC_TRNS, KC_PGDN,
KC_TRNS, KC_TRNS,
KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS
),
/* Keymap 2: QWERTY overlay
* ,-----------------------------------------. ,-----------------------------------------.
* | | | | | | | | | | | | | [ |
* |------+------+------+------+------+------| |------+------+------+------+------+------|
* | | Q | W | E | R | T | | Y | U | I | O | P | ] |
* |------+------+------+------+------+------| |------+------+------+------+------+------|
* | | A | S | D | F | G | | H | J | K | L | ; | '" |
* |------+------+------+------+------+------| |------+------+------+------+------+------|
* | | Z | X | C | V | B | | N | M | , | . | / | |
* |------+------+------+------+------+------' `------+------+------+------+------+------|
* | | | | | | | | | - | \ | |
* `----------------------------------' `----------------------------------'
* ,-------------. ,-------------.
* | | | | | |
* ,------|------|------| |------+------+------.
* | | | | | | | |
* | | |------| |------| | |
* | | | | | | | |
* `--------------------' `--------------------'
*
*/
// QWERTY
[QWER] = LAYOUT_dactyl(
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_Q, KC_W, KC_E, KC_R, KC_T,
KC_TRNS, KC_A, KC_S, KC_D, KC_F, KC_G,
KC_TRNS, KC_Z, KC_X, KC_C, KC_V, KC_B,
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
KC_TRNS, KC_TRNS,
KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS,
// right hand
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_LBRC,
KC_Y, KC_U, KC_I, KC_O, KC_P, KC_RBRC,
KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT,
KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_TRNS,
KC_TRNS, KC_TRNS, KC_MINS, KC_BSLS, KC_TRNS,
KC_TRNS, KC_TRNS,
KC_TRNS,
KC_TRNS, KC_TRNS, KC_TRNS
),
};
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if (record->event.pressed) {
switch(keycode) {
case COLON_EQ:
SEND_STRING(":=");
return false;
break;
}
}
return true;
}
// Runs just one time when the keyboard initializes.
void matrix_init_user(void) {
};
// Runs constantly in the background, in a loop.
void matrix_scan_user(void) {};

View File

@ -1,6 +0,0 @@
# Erincalling Dactyl keymap
## Changelog
* Nov 2017:
* Ported and adapted from the ergodox-firmware layout I'd been using

View File

@ -1,5 +1,4 @@
/*
Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com>
Copyright 2017 Erin Call <hello@erincall.com>
@ -16,10 +15,6 @@ 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/>.
*/
/*
* scan matrix
*/
#include <stdint.h>
#include <stdbool.h>
#include <avr/io.h>
@ -30,48 +25,58 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "util.h"
#include "matrix.h"
#include "daktil.h"
#include "i2cmaster.h"
#ifdef DEBUG_MATRIX_SCAN_RATE
#include "timer.h"
#endif
#include "i2c_master.h"
#include "timer.h"
/*
* This constant define not debouncing time in msecs, but amount of matrix
* scan loops which should be made to get stable debounced results.
*
* On the Dactyl, the matrix scan rate is relatively low, because
* communicating with the left hand's I/O expander is slower than simply
* selecting local pins.
* Now it's only 317 scans/second, or about 3.15 msec/scan.
* According to Cherry specs, debouncing time is 5 msec.
*
* And so, there is no sense to have DEBOUNCE higher than 2.
*/
/* Set 0 if debouncing isn't needed */
#ifndef DEBOUNCE
# define DEBOUNCE 5
# define DEBOUNCE 5
#endif
#if (DEBOUNCE > 0)
static uint16_t debouncing_time;
static bool debouncing = false;
#endif
#ifdef MATRIX_MASKED
extern const matrix_row_t matrix_mask[];
#endif
#if (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
static const uint8_t onboard_row_pins[MATRIX_ROWS] = MATRIX_ONBOARD_ROW_PINS;
static const uint8_t onboard_col_pins[MATRIX_COLS] = MATRIX_ONBOARD_COL_PINS;
static const bool col_expanded[MATRIX_COLS] = COL_EXPANDED;
#endif
/* matrix state(1:on, 0:off) */
static matrix_row_t matrix[MATRIX_ROWS];
// Debouncing: store for each key the number of scans until it's eligible to
// change. When scanning the matrix, ignore any changes in keys that have
// already changed in the last DEBOUNCE scans.
static uint8_t debounce_matrix[MATRIX_ROWS * MATRIX_COLS];
static matrix_row_t matrix_debouncing[MATRIX_ROWS];
static matrix_row_t read_cols(uint8_t row);
static void init_cols(void);
static void unselect_rows(void);
static void select_row(uint8_t row);
static uint8_t mcp23018_reset_loop;
#ifdef DEBUG_MATRIX_SCAN_RATE
uint32_t matrix_timer;
uint32_t matrix_scan_count;
#if (DIODE_DIRECTION == COL2ROW)
static const uint8_t expander_col_pins[MATRIX_COLS] = MATRIX_EXPANDER_COL_PINS;
static void init_cols(void);
static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row);
static void unselect_rows(void);
static void select_row(uint8_t row);
static void unselect_row(uint8_t row);
#elif (DIODE_DIRECTION == ROW2COL)
static const uint8_t expander_row_pins[MATRIX_ROWS] = MATRIX_EXPANDER_ROW_PINS;
static void init_rows(void);
static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
static void unselect_cols(void);
static void select_col(uint8_t col);
static void unselect_col(uint8_t col);
#endif
static uint8_t expander_reset_loop;
uint8_t mcp23018_status;
uint8_t expander_input_pin_mask;
bool i2c_initialized = false;
#define ROW_SHIFTER ((matrix_row_t)1)
__attribute__ ((weak))
void matrix_init_user(void) {}
@ -89,81 +94,142 @@ void matrix_scan_kb(void) {
matrix_scan_user();
}
inline
uint8_t matrix_rows(void)
{
return MATRIX_ROWS;
}
inline
uint8_t matrix_cols(void)
{
return MATRIX_COLS;
}
void matrix_init(void)
{
// initialize row and col
mcp23018_status = init_mcp23018();
init_expander();
#if (DIODE_DIRECTION == COL2ROW)
unselect_rows();
init_cols();
#elif (DIODE_DIRECTION == ROW2COL)
unselect_cols();
init_rows();
#endif
// initialize matrix state: all keys off
for (uint8_t i=0; i < MATRIX_ROWS; i++) {
matrix[i] = 0;
for (uint8_t j=0; j < MATRIX_COLS; ++j) {
debounce_matrix[i * MATRIX_COLS + j] = 0;
}
matrix_debouncing[i] = 0;
}
#ifdef DEBUG_MATRIX_SCAN_RATE
matrix_timer = timer_read32();
matrix_scan_count = 0;
#endif
matrix_init_kb();
}
void matrix_power_up(void) {
mcp23018_status = init_mcp23018();
unselect_rows();
init_cols();
// initialize matrix state: all keys off
for (uint8_t i=0; i < MATRIX_ROWS; i++) {
matrix[i] = 0;
void init_expander(void) {
if (! i2c_initialized) {
i2c_init();
wait_ms(1000);
}
#ifdef DEBUG_MATRIX_SCAN_RATE
matrix_timer = timer_read32();
matrix_scan_count = 0;
if (! expander_input_pin_mask) {
#if (DIODE_DIRECTION == COL2ROW)
for (int col = 0; col < MATRIX_COLS; col++) {
if (col_expanded[col]) {
expander_input_pin_mask |= (1 << expander_col_pins[col]);
}
}
#elif (DIODE_DIRECTION == ROW2COL)
for (int row = 0; row < MATRIX_ROWS; row++) {
expander_input_pin_mask |= (1 << expander_row_pins[row]);
}
#endif
}
// Returns a matrix_row_t whose bits are set if the corresponding key should be
// eligible to change in this scan.
matrix_row_t debounce_mask(uint8_t row) {
matrix_row_t result = 0;
for (uint8_t j=0; j < MATRIX_COLS; ++j) {
if (debounce_matrix[row * MATRIX_COLS + j]) {
--debounce_matrix[row * MATRIX_COLS + j];
} else {
result |= (1 << j);
}
}
return result;
}
// Report changed keys in the given row. Resets the debounce countdowns
// corresponding to each set bit in 'change' to DEBOUNCE.
void debounce_report(matrix_row_t change, uint8_t row) {
for (uint8_t i = 0; i < MATRIX_COLS; ++i) {
if (change & (1 << i)) {
debounce_matrix[row * MATRIX_COLS + i] = DEBOUNCE;
}
}
/*
Pin direction and pull-up depends on both the diode direction
and on whether the column register is GPIOA or GPIOB
+-------+---------------+---------------+
| | ROW2COL | COL2ROW |
+-------+---------------+---------------+
| GPIOA | input, output | output, input |
+-------+---------------+---------------+
| GPIOB | output, input | input, output |
+-------+---------------+---------------+
*/
#if (EXPANDER_COL_REGISTER == GPIOA)
# if (DIODE_DIRECTION == COL2ROW)
uint8_t direction[2] = {
expander_input_pin_mask,
0,
};
# elif (DIODE_DIRECTION == ROW2COL)
uint8_t direction[2] = {
0,
expander_input_pin_mask,
};
# endif
#elif (EXPANDER_COL_REGISTER == GPIOB)
# if (DIODE_DIRECTION == COL2ROW)
uint8_t direction[2] = {
0,
expander_input_pin_mask,
};
# elif (DIODE_DIRECTION == ROW2COL)
uint8_t direction[2] = {
expander_input_pin_mask,
0,
};
# endif
#endif
// set pull-up
// - unused : off : 0
// - input : on : 1
// - driving : off : 0
#if (EXPANDER_COL_REGISTER == GPIOA)
# if (DIODE_DIRECTION == COL2ROW)
uint8_t pullup[2] = {
expander_input_pin_mask,
0,
};
# elif (DIODE_DIRECTION == ROW2COL)
uint8_t pullup[2] = {
0,
expander_input_pin_mask,
};
# endif
#elif (EXPANDER_COL_REGISTER == GPIOB)
# if (DIODE_DIRECTION == COL2ROW)
uint8_t pullup[2] = {
0,
expander_input_pin_mask,
};
# elif (DIODE_DIRECTION == ROW2COL)
uint8_t pullup[2] = {
expander_input_pin_mask,
0,
};
# endif
#endif
mcp23018_status = i2c_write_register(I2C_ADDR, IODIRA, direction, 2, I2C_TIMEOUT);
if (mcp23018_status) return;
mcp23018_status = i2c_write_register(I2C_ADDR, GPPUA, pullup, 2, I2C_TIMEOUT);
}
uint8_t matrix_scan(void)
{
if (mcp23018_status) { // if there was an error
if (++mcp23018_reset_loop == 0) {
// since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans
if (++expander_reset_loop == 0) {
// since expander_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans
// this will be approx bit more frequent than once per second
print("trying to reset mcp23018\n");
mcp23018_status = init_mcp23018();
print("trying to reset expander\n");
init_expander();
if (mcp23018_status) {
print("left side not responding\n");
} else {
@ -172,49 +238,63 @@ uint8_t matrix_scan(void)
}
}
#ifdef DEBUG_MATRIX_SCAN_RATE
matrix_scan_count++;
#if (DIODE_DIRECTION == COL2ROW)
for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
# if (DEBOUNCE > 0)
bool matrix_changed = read_cols_on_row(matrix_debouncing, current_row);
uint32_t timer_now = timer_read32();
if (TIMER_DIFF_32(timer_now, matrix_timer)>1000) {
print("matrix scan frequency: ");
pdec(matrix_scan_count);
print("\n");
if (matrix_changed) {
debouncing = true;
debouncing_time = timer_read();
}
# else
read_cols_on_row(matrix, current_row);
# endif
}
#elif (DIODE_DIRECTION == ROW2COL)
for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
# if (DEBOUNCE > 0)
bool matrix_changed = read_rows_on_col(matrix_debouncing, current_col);
if (matrix_changed) {
debouncing = true;
debouncing_time = timer_read();
}
# else
read_rows_on_col(matrix, current_col);
# endif
matrix_timer = timer_now;
matrix_scan_count = 0;
}
#endif
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
select_row(i);
wait_us(30); // without this wait read unstable value.
matrix_row_t mask = debounce_mask(i);
matrix_row_t cols = (read_cols(i) & mask) | (matrix[i] & ~mask);
debounce_report(cols ^ matrix[i], i);
matrix[i] = cols;
unselect_rows();
}
# if (DEBOUNCE > 0)
if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCE)) {
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
matrix[i] = matrix_debouncing[i];
}
debouncing = false;
}
# endif
matrix_scan_kb();
return 1;
}
bool matrix_is_modified(void) // deprecated and evidently not called.
{
return true;
}
inline
bool matrix_is_on(uint8_t row, uint8_t col)
{
return (matrix[row] & ((matrix_row_t)1<<col));
return (matrix[row] & (ROW_SHIFTER << col));
}
inline
matrix_row_t matrix_get_row(uint8_t row)
{
#ifdef MATRIX_MASKED
return matrix[row] & matrix_mask[row];
#else
return matrix[row];
#endif
}
void matrix_print(void)
@ -227,198 +307,196 @@ void matrix_print(void)
}
}
uint8_t matrix_key_count(void)
{
uint8_t count = 0;
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
count += bitpop16(matrix[i]);
}
return count;
}
#if (DIODE_DIRECTION == COL2ROW)
/* Column pin configuration
*
* Teensy
* col: 0 1 2 3 4 5
* pin: F0 F1 F4 F5 F6 F7
*
* MCP23018
* col: 0 1 2 3 4 5
* pin: B5 B4 B3 B2 B1 B0
*/
static void init_cols(void)
{
// init on mcp23018
// not needed, already done as part of init_mcp23018()
// init on teensy
// Input with pull-up(DDR:0, PORT:1)
// To je za stran vrec
//DDRF &= ~(1<<7 | 1<<6 | 1<<5 | 1<<4 | 1<<1 | 1<<0);
//PORTF |= (1<<7 | 1<<6 | 1<<5 | 1<<4 | 1<<1 | 1<<0);
// Cist mimo
DDRB &= ~(1<<6 | 1<<3 | 1<<2 | 1<<1 );
PORTB |= (1<<6 | 1<<3 | 1<<2 | 1<<1 );
// Evo to je ze boljse
DDRF &= ~(1<<6 | 1<<7);
PORTF |= (1<<6 | 1<<7);
}
static matrix_row_t read_cols(uint8_t row)
{
if (row < 6) {
if (mcp23018_status) { // if there was an error
return 0;
} else {
uint8_t data = 0;
mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out;
mcp23018_status = i2c_write(GPIOB); if (mcp23018_status) goto out;
mcp23018_status = i2c_start(I2C_ADDR_READ); if (mcp23018_status) goto out;
data = i2c_readNak();
data = ~data;
out:
i2c_stop();
return data;
static void init_cols(void) {
for (uint8_t x = 0; x < MATRIX_COLS; x++) {
if (! col_expanded[x]) {
uint8_t pin = onboard_col_pins[x];
_SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
_SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
}
} else {
// read from teensy
return
/* OLOSH
(PINF&(1<<0) ? 0 : (1<<0)) |
(PINF&(1<<1) ? 0 : (1<<1)) |
(PINF&(1<<4) ? 0 : (1<<2)) |
(PINF&(1<<5) ? 0 : (1<<3)) |
(PINF&(1<<6) ? 0 : (1<<4)) |
(PINF&(1<<7) ? 0 : (1<<5)) ;
(PINB&(1<<6) ? 0 : (1<<0)) |
(PINB&(1<<2) ? 0 : (1<<1)) |
(PINB&(1<<3) ? 0 : (1<<2)) |
(PINB&(1<<1) ? 0 : (1<<3)) |
(PINF&(1<<7) ? 0 : (1<<4)) |
(PINF&(1<<6) ? 0 : (1<<5)) ;
*/
(PINB&(1<<6) ? 0 : (1<<5)) |
(PINB&(1<<2) ? 0 : (1<<4)) |
(PINB&(1<<3) ? 0 : (1<<3)) |
(PINB&(1<<1) ? 0 : (1<<2)) |
(PINF&(1<<7) ? 0 : (1<<1)) |
(PINF&(1<<6) ? 0 : (1<<0)) ;
}
}
/* Row pin configuration
*
* Micro Pro
* row: 6 7 8 9 10 11
* pin: B5 F4 E6 D7 C6 D4
*
* Teensy
* row: 6 7 8 9 10 11
* pin: B1 B2 B3 D2 D3 C6
*
* MCP23018
* row: 0 1 2 3 4 5
* pin: A0 A1 A2 A3 A4 A5
*/
static void unselect_rows(void)
{
// unselect on mcp23018
if (mcp23018_status) { // if there was an error
// do nothing
} else {
// set all rows hi-Z : 1
mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out;
mcp23018_status = i2c_write(GPIOA); if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0xFF); if (mcp23018_status) goto out;
out:
i2c_stop();
static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
// Store last value of row prior to reading
matrix_row_t last_row_value = current_matrix[current_row];
// Clear data in matrix row
current_matrix[current_row] = 0;
// Select row and wait for row selection to stabilize
select_row(current_row);
wait_us(30);
// Read columns from expander, unless it's in an error state
if (! mcp23018_status) {
uint8_t state = 0;
mcp23018_status = i2c_read_register(I2C_ADDR, EXPANDER_COL_REGISTER, &state, 1, I2C_TIMEOUT);
if (! mcp23018_status) {
current_matrix[current_row] |= (~state) & expander_input_pin_mask;
}
}
// Read columns from onboard pins
for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
if (! col_expanded[col_index]) {
uint8_t pin = onboard_col_pins[col_index];
uint8_t pin_state = (_SFR_IO8(pin >> 4) & _BV(pin & 0xF));
current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index);
}
}
unselect_row(current_row);
return (last_row_value != current_matrix[current_row]);
}
static void select_row(uint8_t row) {
// select on expander, unless it's in an error state
if (! mcp23018_status) {
// set active row low : 0
// set other rows hi-Z : 1
uint8_t port = 0xFF & ~(1<<row);
mcp23018_status = i2c_write_register(I2C_ADDR, EXPANDER_ROW_REGISTER, &port, 1, I2C_TIMEOUT);
}
// select on teensy
uint8_t pin = onboard_row_pins[row];
_SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
_SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
}
static void unselect_row(uint8_t row)
{
// No need to explicitly unselect expander pins--their I/O state is
// set simultaneously, with a single bitmask sent to i2c_write. When
// select_row selects a single pin, it implicitly unselects all the
// other ones.
// unselect on teensy
// Hi-Z(DDR:0, PORT:0) to unselect
/* spet mimo jojoj
DDRB &= ~(1<<1 | 1<<2 | 1<<3);
PORTB &= ~(1<<1 | 1<<2 | 1<<3);
DDRD &= ~(1<<2 | 1<<3);
PORTD &= ~(1<<2 | 1<<3);
DDRC &= ~(1<<6);
PORTC &= ~(1<<6);
*/
DDRB &= ~(1<<5);
PORTB &= ~(1<<5);
DDRC &= ~(1<<6);
PORTC &= ~(1<<6);
DDRD &= ~(1<<4 | 1<<7);
PORTD &= ~(1<<4 | 1<<7);
DDRE &= ~(1<<6);
PORTE &= ~(1<<6);
DDRF &= ~(1<<4);
PORTF &= ~(1<<4);
uint8_t pin = onboard_row_pins[row];
_SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // OUT
_SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // LOW
}
/* Row pin configuration
*
* Teensy
* row: 6 7 8 9 10 11
* pin: B1 B2 B3 D2 D3 C6
*
* MCP23018
* row: 0 1 2 3 4 5
* pin: A0 A1 A2 A3 A4 A5
*/
static void select_row(uint8_t row)
static void unselect_rows(void) {
for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
unselect_row(x);
}
}
#elif (DIODE_DIRECTION == ROW2COL)
static void init_rows(void)
{
if (row < 6) {
// select on mcp23018
for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
uint8_t pin = onboard_row_pins[x];
_SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
_SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
}
}
static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
{
bool matrix_changed = false;
uint8_t column_state = 0;
//select col and wait for selection to stabilize
select_col(current_col);
wait_us(30);
if (current_col < 6) {
// read rows from expander
if (mcp23018_status) {
// it's already in an error state; nothing we can do
return false;
}
mcp23018_status = i2c_read_register(I2C_ADDR, EXPANDER_ROW_REGISTER, &column_state, 1, I2C_TIMEOUT);
column_state = ~column_state;
} else {
for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
if ((_SFR_IO8(onboard_row_pins[current_row] >> 4) & _BV(onboard_row_pins[current_row] & 0xF)) == 0) {
column_state |= (1 << current_row);
}
}
}
for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
// Store last value of row prior to reading
matrix_row_t last_row_value = current_matrix[current_row];
if (column_state & (1 << current_row)) {
// key closed; set state bit in matrix
current_matrix[current_row] |= (ROW_SHIFTER << current_col);
} else {
// key open; clear state bit in matrix
current_matrix[current_row] &= ~(ROW_SHIFTER << current_col);
}
// Determine whether the matrix changed state
if ((last_row_value != current_matrix[current_row]) && !(matrix_changed))
{
matrix_changed = true;
}
}
unselect_col(current_col);
return matrix_changed;
}
static void select_col(uint8_t col)
{
if (col_expanded[col]) {
// select on expander
if (mcp23018_status) { // if there was an error
// do nothing
} else {
// set active row low : 0
// set other rows hi-Z : 1
mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out;
mcp23018_status = i2c_write(GPIOA); if (mcp23018_status) goto out;
mcp23018_status = i2c_write(0xFF & ~(1<<row)); if (mcp23018_status) goto out;
out:
i2c_stop();
// set active col low : 0
// set other cols hi-Z : 1
uint8_t port = 0xFF & ~(1<<col);
mcp23018_status = i2c_write_register(I2C_ADDR, EXPANDER_COL_REGISTER, &port, 1, I2C_TIMEOUT);
}
} else {
// select on teensy
// Output low(DDR:1, PORT:0) to select
switch (row) {
case 11:
DDRB |= (1<<5);
PORTB &= ~(1<<5);
break;
case 10:
DDRF |= (1<<4);
PORTF &= ~(1<<4);
break;
case 9:
DDRE |= (1<<6);
PORTE &= ~(1<<6);
break;
case 8:
DDRD |= (1<<7);
PORTD &= ~(1<<7);
break;
case 7:
DDRC |= (1<<6);
PORTC &= ~(1<<6);
break;
case 6:
DDRD |= (1<<4);
PORTD &= ~(1<<4);
break;
}
uint8_t pin = onboard_col_pins[col];
_SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
_SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
}
}
static void unselect_col(uint8_t col)
{
if (col_expanded[col]) {
// No need to explicitly unselect expander pins--their I/O state is
// set simultaneously, with a single bitmask sent to i2c_write. When
// select_col selects a single pin, it implicitly unselects all the
// other ones.
} else {
// unselect on teensy
uint8_t pin = onboard_col_pins[col];
_SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
_SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
}
}
static void unselect_cols(void)
{
for(uint8_t x = 0; x < MATRIX_COLS; x++) {
unselect_col(x);
}
}
#endif
__attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); }
__attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); }
__attribute__((weak)) void matrix_init_user(void) {}
__attribute__((weak)) void matrix_scan_user(void) {}

View File

@ -15,8 +15,9 @@
#----------------------------------------------------------------------------
# # project specific files
SRC = twimaster.c \
#SRC = twimaster.c \
matrix.c
src = matrix.c
# MCU name
MCU = atmega32u4
@ -67,3 +68,6 @@ OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
#OPT_DEFS += -DBOOTLOADER_SIZE=512
CUSTOM_MATRIX = yes
OLED_ENABLE = yes
OLED_DRIVER = ssd1306
OLED_TRANSPORT = i2c

View File

@ -9,7 +9,7 @@
#include <inttypes.h>
#include <compat/twi.h>
#include <i2cmaster.h>
#include <i2c_master.h>
/* define CPU frequency in Hz here if not defined in Makefile */
#ifndef F_CPU