forked from qmk/qmk_firmware
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add launch_heavy_1 * Gets basic keymap functionality working on launch_heavy_1 LEDs are not working yet. * Fix mapping of column M on the tenkey * Fix launch heavy LEDS * Increment PRODUCT_ID to 0007 * launch_heavy_1: Update `LAYOUT` define to what configurator expects `keyboard-configurator/layouts.py` relies on the naming here to follow this convention. It shouldn't impact behavior. * Add Levi's Heavy layout * Align keyboard led to keyswitch map Followed argb trace for 10 key from kicad file * Fix spacing * Increase EEPROM size to 2048 for Heavy Ok because our new EC has double the EEPROM of previous launch keyboards https://www.microchip.com/en-us/product/AT90USB646 Co-authored-by: 13r0ck <bnr@tuta.io> Co-authored-by: Ian Douglas Scott <idscott@system76.com>
- Loading branch information
Showing
12 changed files
with
1,514 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
## Flashing firmware: | ||
* Clone this repository and `cd` into the `qmk_firmware` directory. | ||
* After cloning, you probably need to run `make git-submodule` as well as `./util/qmk_install`. | ||
- You may also need to install dependencies: `sudo apt install avrdude gcc-avr avr-libc` | ||
* To build the firmware without flashing the keyboard, use `make (keyboard name):(layout name)` | ||
- For example, if you want to build the `default` layout for the Launch keyboard, run: | ||
``` | ||
make system76/launch_heavy_1:default | ||
``` | ||
* To flash the firmware, you'll use the same build command, but with `dfu` added to the end: | ||
``` | ||
make system76/launch_heavy_1:default:dfu | ||
``` | ||
- After it builds, you will see a repeating message that says: | ||
``` | ||
dfu-programmer: no device present. | ||
ERROR: Bootloader not found. Trying again in 5s. | ||
``` | ||
Next, unplug your keyboard from your computer, hold the ESC key (while the keyboard is unplugged), and plug the keyboard back in while holding the ESC key. Once the keyboard is plugged in, the ESC key can be released. | ||
* Note: on some distros, dfu-programmer has trouble detecting the keyboard unless you run the `make` command with `sudo`. | ||
* To flash the firmware using ISP, you will need a USBasp device, and a tag connect cable. | ||
- Build the firmware and bootloader with: | ||
``` | ||
make system76/launch_heavy_1:default:production | ||
``` | ||
- Run avrdude to flash the fuses: | ||
``` | ||
avrdude -c usbasp -p at90usb646 -U lfuse:w:0x5E:m -U hfuse:w:0xDB:m -U efuse:w:0xFB:m -U lock:w:0xFF:m | ||
``` | ||
- Run avrdude to flash the ROM: | ||
``` | ||
avrdude -c usbasp -p at90usb646 -U flash:w:system76_launch_heavy_1_default_production.hex | ||
``` | ||
|
||
## Making your own layout: | ||
If you want to create your own layout, go to the `keymaps` directory and copy one of the maps in there. It will likely be easiest to start with the default layout, but the other layouts in there may be helpful references. The name of the directory you create will be the name of your layout. To prevent build errors, it is recommended to use only lowercase letters, underscores, and numbers for the name of your layout. | ||
|
||
Inside of each layout directory, there is a file called `keymap.c`. The commented out grid area in this file is a visual reference for the actual key assignments below it. When modifying a layout, modifying this visual reference first makes it easier to design a layout, as well as keeping the actual layout below it organized. | ||
|
||
Once your layout is designed, change the keycodes below to match your design. A full list of available keycodes can be found in the [QMK docs](https://beta.docs.qmk.fm/reference/keycodes). Use the shorter keycode alias to help keep these lined up (e.g. use `KC_ESC` instead of `KC_ESCAPE`). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
#ifndef CONFIG_H | ||
#define CONFIG_H | ||
|
||
#include "config_common.h" | ||
|
||
/* USB Device descriptor parameter */ | ||
#define VENDOR_ID 0x3384 | ||
#define PRODUCT_ID 0x0007 | ||
#define DEVICE_VER 0x0001 | ||
#define MANUFACTURER System76 | ||
#define PRODUCT Launch Heavy Configurable Keyboard (launch_heavy_1) | ||
#define DESCRIPTION Launch Heavy Configurable Keyboard (launch_heavy_1) | ||
|
||
/* key matrix size */ | ||
#define MATRIX_ROWS 12 | ||
#define MATRIX_COLS 14 | ||
|
||
/* key matrix pins */ | ||
#define MATRIX_ROW_PINS { F0, F1, F2, F3, F4, F5, D2, D4, D5, D6, D7, E0 } | ||
#define MATRIX_COL_PINS { C6, C5, C4, C3, C2, C1, C7, A7, A6, A5, A4, E6, C0, E7 } | ||
#define UNUSED_PINS | ||
|
||
/* COL2ROW or ROW2COL */ | ||
#define DIODE_DIRECTION COL2ROW | ||
|
||
/* Set 0 if debouncing isn't needed */ | ||
#define DEBOUNCE 5 | ||
|
||
// NKRO must be used | ||
#define FORCE_NKRO | ||
|
||
#if RGBLIGHT_ENABLE | ||
#define RGB_DI_PIN F7 | ||
#define RGBLED_NUM 70 | ||
#define RGBLIGHT_ANIMATIONS | ||
// Limit brightness to support USB-A at 0.5A | ||
//TODO: do this dynamically based on power source | ||
#define RGBLIGHT_LIMIT_VAL 176 | ||
#endif | ||
|
||
#if RGB_MATRIX_ENABLE | ||
#define RGB_DI_PIN F7 | ||
#define DRIVER_LED_TOTAL 105 | ||
#define RGB_MATRIX_KEYPRESSES // reacts to keypresses | ||
//#define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (instead of keypresses) | ||
//#define RGB_MATRIX_FRAMEBUFFER_EFFECTS | ||
#define RGB_DISABLE_TIMEOUT 0 // number of milliseconds to wait until rgb automatically turns off | ||
#define RGB_DISABLE_AFTER_TIMEOUT 0 // OBSOLETE: number of ticks to wait until disabling effects | ||
#define RGB_DISABLE_WHEN_USB_SUSPENDED true // turn off effects when suspended | ||
#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 176 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255 | ||
#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_RAINBOW_MOVING_CHEVRON // Sets the default mode, if none has been set | ||
#define RGB_MATRIX_STARTUP_HUE 142 // 200 degrees | ||
#define RGB_MATRIX_STARTUP_SAT 255 | ||
#define RGB_MATRIX_STARTUP_VAL RGB_MATRIX_MAXIMUM_BRIGHTNESS | ||
#define RGB_MATRIX_STARTUP_SPD 127 | ||
#define RGB_MATRIX_DISABLE_KEYCODES // disables control of rgb matrix by keycodes (must use code functions to control the feature) | ||
#endif | ||
|
||
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ | ||
#define LOCKING_SUPPORT_ENABLE | ||
|
||
/* Locking resynchronize hack */ | ||
#define LOCKING_RESYNC_ENABLE | ||
|
||
// EEPROM { | ||
#define EEPROM_SIZE 2048 | ||
|
||
// TODO: refactor with new user EEPROM code (coming soon) | ||
#define EEPROM_MAGIC 0x76EC | ||
#define EEPROM_MAGIC_ADDR 64 | ||
// Bump this every time we change what we store | ||
// This will automatically reset the EEPROM with defaults | ||
// and avoid loading invalid data from the EEPROM | ||
#define EEPROM_VERSION 0x02 | ||
#define EEPROM_VERSION_ADDR (EEPROM_MAGIC_ADDR + 2) | ||
// } EEPROM | ||
|
||
// Dynamic keyboard support { | ||
#define DYNAMIC_KEYMAP_LAYER_COUNT 4 | ||
// Dynamic keymap starts after EEPROM version | ||
#define DYNAMIC_KEYMAP_EEPROM_ADDR (EEPROM_VERSION_ADDR + 1) | ||
// `* 2` Beacuse each key needs 16 bits (2 bytes) for storing the keycode | ||
#define DYNAMIC_KEYMAP_EEPROM_SIZE (DYNAMIC_KEYMAP_LAYER_COUNT * MATRIX_ROWS * MATRIX_COLS * 2) | ||
// Dynamic macro starts after dynamic keymaps, it is disabled | ||
#define DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR (DYNAMIC_KEYMAP_EEPROM_ADDR + DYNAMIC_KEYMAP_EEPROM_SIZE) | ||
#define DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE 0 | ||
#define DYNAMIC_KEYMAP_MACRO_COUNT 0 | ||
// } Dynamic keyboard support | ||
|
||
// System76 EC { | ||
#define SYSTEM76_EC_EEPROM_ADDR (DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR + DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE) | ||
#define SYSTEM76_EC_EEPROM_SIZE (EEPROM_SIZE - SYSTEM76_EC_EEPROM_ADDR) | ||
// } System76 EC | ||
|
||
#endif // CONFIG_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
#include <stdio.h> | ||
#include <avr/io.h> | ||
#include <util/twi.h> | ||
|
||
#include "i2c.h" | ||
|
||
#define TIMEOUT (F_CPU/1000) | ||
|
||
// Initialize I2C with specified buad rate | ||
void i2c_init(unsigned long baud) { | ||
TWAR = 0; | ||
TWBR = (uint8_t)(((F_CPU / baud) - 16 ) / 2); | ||
TWCR = 0; | ||
} | ||
|
||
// Send an I2C start condition, a 7-bit address, and a read bit | ||
// Returns zero on success or negative number on error | ||
int i2c_start(uint8_t addr, bool read) { | ||
uint32_t count; | ||
uint8_t twst; | ||
|
||
// transmit START condition | ||
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); | ||
// wait for end of transmission | ||
count = TIMEOUT; | ||
while(!(TWCR & (1<<TWINT)) && count > 0) count -= 1; | ||
if (count == 0) return -1; | ||
|
||
// check if the start condition was successfully transmitted | ||
twst = TW_STATUS & 0xF8; | ||
if ((twst != TW_START) && (twst != TW_REP_START)) return -1; | ||
|
||
// load slave addr into data register | ||
TWDR = ((addr << 1) | read); | ||
// start transmission of addr | ||
TWCR = (1<<TWINT) | (1<<TWEN); | ||
// wait for end of transmission | ||
count = TIMEOUT; | ||
while(!(TWCR & (1<<TWINT)) && count > 0) count -= 1; | ||
if (count == 0) return -1; | ||
|
||
// check if the device has acknowledged the READ / WRITE mode | ||
twst = TW_STATUS & 0xF8; | ||
if ((twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK)) return -1; | ||
|
||
return 0; | ||
} | ||
|
||
// Send an I2C stop condition | ||
// Always successful | ||
void i2c_stop(void) { | ||
// transmit STOP condition | ||
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); | ||
//TODO: timeout? | ||
while (TWCR & (1<<TWSTO)); | ||
} | ||
|
||
// Write data to the I2C bus | ||
// Returns bytes written on success or negative number on error | ||
int i2c_write(uint8_t * data, int length) { | ||
int i; | ||
for (i = 0; i < length; i++) { | ||
// load data into data register | ||
TWDR = data[i]; | ||
// start transmission of data | ||
TWCR = (1<<TWINT) | (1<<TWEN); | ||
// wait for end of transmission | ||
uint32_t count = TIMEOUT; | ||
while(!(TWCR & (1<<TWINT)) && count > 0) count -= 1; | ||
// timed out | ||
if (count == 0) return -1; | ||
// failed to receive ack | ||
if((TWSR & 0xF8) != TW_MT_DATA_ACK) return -1; | ||
} | ||
|
||
return i; | ||
} | ||
|
||
// Read a byte from the I2C bus, sending an ack if specified | ||
// Returns byte data on success or negative number on error | ||
int i2c_read_byte(bool ack) { | ||
if (ack) { | ||
// start TWI module and acknowledge data after reception | ||
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA); | ||
} else { | ||
// start receiving without acknowledging reception | ||
TWCR = (1<<TWINT) | (1<<TWEN); | ||
} | ||
// wait for end of transmission | ||
uint32_t count = TIMEOUT; | ||
while(!(TWCR & (1<<TWINT)) && count > 0) count -= 1; | ||
if (count == 0) return -1; | ||
// return received data from TWDR | ||
return (int)TWDR; | ||
} | ||
|
||
// Read data from the I2C bus | ||
// Returns bytes read on success or negative number on error | ||
int i2c_read(uint8_t * data, int length) { | ||
int res; | ||
int i; | ||
|
||
for (i = 0; i < length; i++) { | ||
bool ack = (i + 1) < length; | ||
res = i2c_read_byte(ack); | ||
if (res < 0) return res; | ||
data[i] = (uint8_t)res; | ||
} | ||
|
||
return i; | ||
} | ||
|
||
// Receive data from a specified address on the I2C bus | ||
// Returns bytes read on success or negative number on error | ||
int i2c_recv(uint8_t addr, uint8_t* data, int length) { | ||
int res = 0; | ||
|
||
res = i2c_start(addr, true); | ||
if (res < 0) return res; | ||
|
||
res = i2c_read(data, length); | ||
if (res < 0) return res; | ||
|
||
i2c_stop(); | ||
|
||
return res; | ||
} | ||
|
||
// Send data to a specified address on the I2C bus | ||
// Returns bytes written on success or negative number on error | ||
int i2c_send(uint8_t addr, uint8_t* data, int length) { | ||
int res = 0; | ||
|
||
res = i2c_start(addr, false); | ||
if (res < 0) return res; | ||
|
||
res = i2c_write(data, length); | ||
if (res < 0) return res; | ||
|
||
i2c_stop(); | ||
|
||
return res; | ||
} | ||
|
||
// Get data from a specified address and register on the I2C bus | ||
// Returns bytes read on success or negative number on error | ||
int i2c_get(uint8_t addr, uint8_t reg, uint8_t* data, int length) { | ||
int res = 0; | ||
|
||
res = i2c_start(addr, false); | ||
if (res < 0) return res; | ||
|
||
res = i2c_write(®, 1); | ||
if (res < 0) return res; | ||
|
||
return i2c_recv(addr, data, length); | ||
} | ||
|
||
// Set data in a specified address and register on the I2C bus | ||
// Returns bytes written on success or negative number on error | ||
int i2c_set(uint8_t addr, uint8_t reg, uint8_t* data, int length) { | ||
int res = 0; | ||
|
||
res = i2c_start(addr, false); | ||
if (res < 0) return res; | ||
|
||
res = i2c_write(®, 1); | ||
if (res < 0) return res; | ||
|
||
res = i2c_write(data, length); | ||
if (res < 0) return res; | ||
|
||
i2c_stop(); | ||
|
||
return res; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
#ifndef I2C_H | ||
#define I2C_H | ||
|
||
#include <stdbool.h> | ||
#include <stdint.h> | ||
|
||
// Initialize I2C with specified buad rate | ||
void i2c_init(unsigned long baud); | ||
|
||
// Send an I2C start condition, a 7-bit address, and a read bit | ||
// Returns zero on success or negative number on error | ||
int i2c_start(uint8_t addr, bool read); | ||
|
||
// Send an I2C stop condition | ||
// Always successful | ||
void i2c_stop(void); | ||
|
||
// Write data to the I2C bus | ||
// Returns bytes written on success or negative number on error | ||
int i2c_write(uint8_t * data, int length); | ||
|
||
// Read a byte from the I2C bus, sending an ack if specified | ||
// Returns byte data on success or negative number on error | ||
int i2c_read_byte(bool ack); | ||
|
||
// Read data from the I2C bus | ||
// Returns bytes read on success or negative number on error | ||
int i2c_read(uint8_t * data, int length); | ||
|
||
// Receive data from a specified address on the I2C bus | ||
// Returns bytes read on success or negative number on error | ||
int i2c_recv(uint8_t addr, uint8_t* data, int length); | ||
|
||
// Send data to a specified address on the I2C bus | ||
// Returns bytes written on success or negative number on error | ||
int i2c_send(uint8_t addr, uint8_t* data, int length); | ||
|
||
// Get data from a specified address and register on the I2C bus | ||
// Returns bytes read on success or negative number on error | ||
int i2c_get(uint8_t addr, uint8_t reg, uint8_t* data, int length); | ||
|
||
// Set data in a specified address and register on the I2C bus | ||
// Returns bytes written on success or negative number on error | ||
int i2c_set(uint8_t addr, uint8_t reg, uint8_t* data, int length); | ||
|
||
#endif // I2C_H |
Oops, something went wrong.