commit
						68ceffe53e
					
				| @ -1 +1,17 @@ | ||||
| #include "rev1.h" | ||||
| 
 | ||||
| void led_init_ports() { | ||||
|     // * Set our LED pins as output
 | ||||
|     DDRF |= (1<<0); | ||||
| } | ||||
| 
 | ||||
| void led_set_kb(uint8_t usb_led) { | ||||
|     DDRF |= (1<<0); | ||||
|     if (usb_led & (1<<USB_LED_CAPS_LOCK)) { | ||||
|         // Turn capslock on
 | ||||
|         PORTF |= (1<<0); | ||||
|     } else { | ||||
|         // Turn capslock off
 | ||||
|         PORTF &= ~(1<<0); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -0,0 +1,112 @@ | ||||
| #----------------------------------------------------------------------------
 | ||||
| # On command line:
 | ||||
| #
 | ||||
| # make all = Make software.
 | ||||
| #
 | ||||
| # make clean = Clean out built project files.
 | ||||
| #
 | ||||
| # make coff = Convert ELF to AVR COFF.
 | ||||
| #
 | ||||
| # make extcoff = Convert ELF to AVR Extended COFF.
 | ||||
| #
 | ||||
| # make program = Download the hex file to the device.
 | ||||
| #                Please customize your programmer settings(PROGRAM_CMD)
 | ||||
| #
 | ||||
| # make teensy = Download the hex file to the device, using teensy_loader_cli.
 | ||||
| #               (must have teensy_loader_cli installed).
 | ||||
| #
 | ||||
| # make dfu = Download the hex file to the device, using dfu-programmer (must
 | ||||
| #            have dfu-programmer installed).
 | ||||
| #
 | ||||
| # make flip = Download the hex file to the device, using Atmel FLIP (must
 | ||||
| #             have Atmel FLIP installed).
 | ||||
| #
 | ||||
| # make dfu-ee = Download the eeprom file to the device, using dfu-programmer
 | ||||
| #               (must have dfu-programmer installed).
 | ||||
| #
 | ||||
| # make flip-ee = Download the eeprom file to the device, using Atmel FLIP
 | ||||
| #                (must have Atmel FLIP installed).
 | ||||
| #
 | ||||
| # make debug = Start either simulavr or avarice as specified for debugging, 
 | ||||
| #              with avr-gdb or avr-insight as the front end for debugging.
 | ||||
| #
 | ||||
| # make filename.s = Just compile filename.c into the assembler code only.
 | ||||
| #
 | ||||
| # make filename.i = Create a preprocessed source file for use in submitting
 | ||||
| #                   bug reports to the GCC project.
 | ||||
| #
 | ||||
| # To rebuild project do "make clean" then "make all".
 | ||||
| #----------------------------------------------------------------------------
 | ||||
| 
 | ||||
| # MCU name
 | ||||
| #MCU = at90usb1287
 | ||||
| MCU = atmega32u4 | ||||
| 
 | ||||
| # Processor frequency.
 | ||||
| #     This will define a symbol, F_CPU, in all source code files equal to the
 | ||||
| #     processor frequency in Hz. You can then use this symbol in your source code to
 | ||||
| #     calculate timings. Do NOT tack on a 'UL' at the end, this will be done
 | ||||
| #     automatically to create a 32-bit value in your source code.
 | ||||
| #
 | ||||
| #     This will be an integer division of F_USB below, as it is sourced by
 | ||||
| #     F_USB after it has run through any CPU prescalers. Note that this value
 | ||||
| #     does not *change* the processor frequency - it should merely be updated to
 | ||||
| #     reflect the processor speed set externally so that the code can use accurate
 | ||||
| #     software delays.
 | ||||
| F_CPU = 16000000 | ||||
| 
 | ||||
| 
 | ||||
| #
 | ||||
| # LUFA specific
 | ||||
| #
 | ||||
| # Target architecture (see library "Board Types" documentation).
 | ||||
| ARCH = AVR8 | ||||
| 
 | ||||
| # Input clock frequency.
 | ||||
| #     This will define a symbol, F_USB, in all source code files equal to the
 | ||||
| #     input clock frequency (before any prescaling is performed) in Hz. This value may
 | ||||
| #     differ from F_CPU if prescaling is used on the latter, and is required as the
 | ||||
| #     raw input clock is fed directly to the PLL sections of the AVR for high speed
 | ||||
| #     clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
 | ||||
| #     at the end, this will be done automatically to create a 32-bit value in your
 | ||||
| #     source code.
 | ||||
| #
 | ||||
| #     If no clock division is performed on the input clock inside the AVR (via the
 | ||||
| #     CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
 | ||||
| F_USB = $(F_CPU) | ||||
| 
 | ||||
| # Interrupt driven control endpoint task(+60)
 | ||||
| OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT | ||||
| 
 | ||||
| 
 | ||||
| # Boot Section Size in *bytes*
 | ||||
| #   Teensy halfKay   512
 | ||||
| #   Teensy++ halfKay 1024
 | ||||
| #   Atmel DFU loader 4096
 | ||||
| #   LUFA bootloader  4096
 | ||||
| #   USBaspLoader     2048
 | ||||
| OPT_DEFS += -DBOOTLOADER_SIZE=4096 | ||||
| 
 | ||||
| 
 | ||||
| # Build Options
 | ||||
| #   comment out to disable the options.
 | ||||
| #
 | ||||
| BOOTMAGIC_ENABLE ?= yes		# Virtual DIP switch configuration(+1000) | ||||
| MOUSEKEY_ENABLE ?= yes		# Mouse keys(+4700) | ||||
| EXTRAKEY_ENABLE ?= yes		# Audio control and System control(+450) | ||||
| # CONSOLE_ENABLE ?= yes		# Console for debug(+400)
 | ||||
| # COMMAND_ENABLE ?= yes		# Commands for debug and configuration
 | ||||
| KEYBOARD_LOCK_ENABLE ?= yes	# Allow locking of keyboard via magic key | ||||
| # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
 | ||||
| # SLEEP_LED_ENABLE ?= yes	# Breathing sleep LED during USB suspend
 | ||||
| NKRO_ENABLE ?= yes		# USB Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work | ||||
| # BACKLIGHT_ENABLE ?= yes	# Enable keyboard backlight functionality
 | ||||
| # MIDI_ENABLE ?= YES		# MIDI controls
 | ||||
| # UNICODE_ENABLE ?= YES		# Unicode
 | ||||
| # BLUETOOTH_ENABLE ?= yes	# Enable Bluetooth with the Adafruit EZ-Key HID
 | ||||
| RGBLIGHT_ENABLE ?= yes          # Enable RGB Underglow | ||||
| 
 | ||||
| ifndef QUANTUM_DIR | ||||
| 	include ../../../../Makefile | ||||
| endif | ||||
| 
 | ||||
| After Width: | Height: | Size: 1015 KiB | 
| @ -0,0 +1,190 @@ | ||||
| /*
 | ||||
| Copyright 2012 Jun Wako <wakojun@gmail.com> | ||||
| 
 | ||||
| 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/>.
 | ||||
| */ | ||||
| 
 | ||||
| #ifndef CONFIG_H | ||||
| #define CONFIG_H | ||||
| 
 | ||||
| #include "config_common.h" | ||||
| 
 | ||||
| /* USB Device descriptor parameter */ | ||||
| #define VENDOR_ID    0xFEED | ||||
| #define PRODUCT_ID   0x6060 | ||||
| #define DEVICE_VER   0x0001 | ||||
| #define MANUFACTURER    geekhack | ||||
| #define PRODUCT         GH60 | ||||
| #define DESCRIPTION     t.m.k. keyboard firmware for GH60 | ||||
| 
 | ||||
| /* key matrix size */ | ||||
| #define MATRIX_ROWS 5 | ||||
| #define MATRIX_COLS 14 | ||||
| 
 | ||||
| /*
 | ||||
|  * Keyboard Matrix Assignments | ||||
|  * | ||||
|  * Change this to how you wired your keyboard | ||||
|  * COLS: AVR pins used for columns, left to right | ||||
|  * ROWS: AVR pins used for rows, top to bottom | ||||
|  * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode) | ||||
|  *         ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode) | ||||
|  * | ||||
| */ | ||||
|  #define MATRIX_ROW_PINS { D0, D1, D2, D3, D5 } | ||||
| // Rev A
 | ||||
| // #define MATRIX_COL_PINS { F0, F1, E6, C7, C6, B6, D4, B1, B0, B5, B4, D7, D6, B3 }
 | ||||
| // Rev B/C
 | ||||
|    #define MATRIX_COL_PINS { F0, F1, E6, C7, C6, B6, D4, B1, B7, B5, B4, D7, D6, B3 } | ||||
| #define UNUSED_PINS | ||||
| 
 | ||||
| /* COL2ROW or ROW2COL */ | ||||
| #define DIODE_DIRECTION COL2ROW | ||||
| 
 | ||||
| /* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */ | ||||
| #define DEBOUNCING_DELAY 5 | ||||
| 
 | ||||
| /* define if matrix has ghost (lacks anti-ghosting diodes) */ | ||||
| //#define MATRIX_HAS_GHOST
 | ||||
| 
 | ||||
| /* number of backlight levels */ | ||||
| #define BACKLIGHT_LEVELS 3 | ||||
| 
 | ||||
| /* 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 | ||||
| 
 | ||||
| /*
 | ||||
|  * Force NKRO | ||||
|  * | ||||
|  * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved | ||||
|  * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the | ||||
|  * makefile for this to work.) | ||||
|  * | ||||
|  * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N) | ||||
|  * until the next keyboard reset. | ||||
|  * | ||||
|  * NKRO may prevent your keystrokes from being detected in the BIOS, but it is | ||||
|  * fully operational during normal computer usage. | ||||
|  * | ||||
|  * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N) | ||||
|  * or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by | ||||
|  * bootmagic, NKRO mode will always be enabled until it is toggled again during a | ||||
|  * power-up. | ||||
|  * | ||||
|  */ | ||||
| //#define FORCE_NKRO
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Magic Key Options | ||||
|  * | ||||
|  * Magic keys are hotkey commands that allow control over firmware functions of | ||||
|  * the keyboard. They are best used in combination with the HID Listen program, | ||||
|  * found here: https://www.pjrc.com/teensy/hid_listen.html
 | ||||
|  * | ||||
|  * The options below allow the magic key functionality to be changed. This is | ||||
|  * useful if your keyboard/keypad is missing keys and you want magic key support. | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| /* key combination for magic key command */ | ||||
| #define IS_COMMAND() ( \ | ||||
|   keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \ | ||||
| ) | ||||
| 
 | ||||
| /* control how magic key switches layers */ | ||||
| //#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS true
 | ||||
| //#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS true
 | ||||
| //#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM false
 | ||||
| 
 | ||||
| /* override magic key keymap */ | ||||
| //#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS
 | ||||
| //#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS
 | ||||
| //#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM
 | ||||
| //#define MAGIC_KEY_HELP1     H
 | ||||
| //#define MAGIC_KEY_HELP2     SLASH
 | ||||
| //#define MAGIC_KEY_DEBUG     D
 | ||||
| //#define MAGIC_KEY_DEBUG_MATRIX  X
 | ||||
| //#define MAGIC_KEY_DEBUG_KBD   K
 | ||||
| //#define MAGIC_KEY_DEBUG_MOUSE  M
 | ||||
| //#define MAGIC_KEY_VERSION    V
 | ||||
| //#define MAGIC_KEY_STATUS     S
 | ||||
| //#define MAGIC_KEY_CONSOLE    C
 | ||||
| //#define MAGIC_KEY_LAYER0_ALT1  ESC
 | ||||
| //#define MAGIC_KEY_LAYER0_ALT2  GRAVE
 | ||||
| //#define MAGIC_KEY_LAYER0     0
 | ||||
| //#define MAGIC_KEY_LAYER1     1
 | ||||
| //#define MAGIC_KEY_LAYER2     2
 | ||||
| //#define MAGIC_KEY_LAYER3     3
 | ||||
| //#define MAGIC_KEY_LAYER4     4
 | ||||
| //#define MAGIC_KEY_LAYER5     5
 | ||||
| //#define MAGIC_KEY_LAYER6     6
 | ||||
| //#define MAGIC_KEY_LAYER7     7
 | ||||
| //#define MAGIC_KEY_LAYER8     8
 | ||||
| //#define MAGIC_KEY_LAYER9     9
 | ||||
| //#define MAGIC_KEY_BOOTLOADER   PAUSE
 | ||||
| //#define MAGIC_KEY_LOCK      CAPS
 | ||||
| //#define MAGIC_KEY_EEPROM     E
 | ||||
| //#define MAGIC_KEY_NKRO      N
 | ||||
| //#define MAGIC_KEY_SLEEP_LED   Z
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Feature disable options | ||||
|  * These options are also useful to firmware size reduction. | ||||
|  */ | ||||
| 
 | ||||
| /* disable debug print */ | ||||
| //#define NO_DEBUG
 | ||||
| 
 | ||||
| /* disable print */ | ||||
| //#define NO_PRINT
 | ||||
| 
 | ||||
| /* disable action features */ | ||||
| //#define NO_ACTION_LAYER
 | ||||
| //#define NO_ACTION_TAPPING
 | ||||
| //#define NO_ACTION_ONESHOT
 | ||||
| //#define NO_ACTION_MACRO
 | ||||
| //#define NO_ACTION_FUNCTION
 | ||||
| 
 | ||||
| /*
 | ||||
|  * RGB Underglow | ||||
|  * These settings are for the F4 by default: | ||||
|  *  | ||||
|  * | ||||
|  * #define ws2812_PORTREG  PORTF | ||||
|  * #define ws2812_DDRREG   DDRF | ||||
|  * #define ws2812_pin PF4 | ||||
|  * #define RGBLED_NUM 14     // Number of LEDs
 | ||||
|  * #define RGBLIGHT_HUE_STEP 10 | ||||
|  * #define RGBLIGHT_SAT_STEP 17 | ||||
|  * #define RGBLIGHT_VAL_STEP 17 | ||||
|  * | ||||
|  * The firmware supports 5 different light effects, and the color (hue, saturation, brightness) can be customized in most effects.  | ||||
|  * To control the underglow, you need to modify your keymap file to assign those functions to some keys/key combinations.  | ||||
|  * For details, please check this keymap. keyboard/planck/keymaps/yang/keymap.c | ||||
| */ | ||||
| 
 | ||||
| /* Deprecated code below
 | ||||
| #define ws2812_PORTREG  PORTF  | ||||
| #define ws2812_DDRREG   DDRF | ||||
| #define ws2812_pin PF4 | ||||
| */  | ||||
| #define RGB_DI_PIN F4 | ||||
| #define RGBLIGHT_TIMER | ||||
| #define RGBLED_NUM 8         // Number of LEDs
 | ||||
| #define RGBLIGHT_HUE_STEP 8 | ||||
| #define RGBLIGHT_SAT_STEP 8 | ||||
| #define RGBLIGHT_VAL_STEP 8 | ||||
| #endif | ||||
| @ -0,0 +1,226 @@ | ||||
| #include "gh60.h" | ||||
| #include "action_layer.h" | ||||
| 
 | ||||
| #define _BL 0 | ||||
| #define _AL 1 | ||||
| #define _FL 2 | ||||
| #define _UL 3 | ||||
| 
 | ||||
| const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | ||||
|    /*
 | ||||
|    *  Base layer, pretty standard ANSI layout.  | ||||
|    * ,-----------------------------------------------------------. | ||||
|    * |FN12| 1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|Backsp | | ||||
|    * |-----------------------------------------------------------| | ||||
|    * |Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|    \| | ||||
|    * |-----------------------------------------------------------| | ||||
|    * |Caps/Fn|  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;|  '|Return | | ||||
|    * |-----------------------------------------------------------| | ||||
|    * |Shift   |  Z|  X|  C|  V|  B|  N|  M|  ,|  .|  /|Shift     | | ||||
|    * |-----------------------------------------------------------| | ||||
|    * |Ctrl|Gui |Alt |      Space             |Alt |Fn  |Menu|Ctrl| | ||||
|    * `-----------------------------------------------------------' | ||||
|    */ | ||||
| 	[_BL] = KEYMAP( | ||||
|         FN12,1,2,3,4,5,6,7,8,9,0,MINS,EQL,BSPC, \ | ||||
| 	TAB,Q,W,E,R,T,Y,U,I,O,P,LBRC,RBRC,BSLS, \ | ||||
|         FN2,A,S,D,F,G,H,J,K,L,SCLN,QUOT,NO,ENT,  \ | ||||
|         LSFT,NO,Z,X,C,V,B,N,M,COMM,DOT,SLSH,NO,RSFT, \ | ||||
|         LCTL,LGUI,LALT,        SPC,      NO,RALT,FN0,APP, RCTL), | ||||
|     | ||||
|    /*  
 | ||||
|    * Locking arrow keys to WASD for when you need dedicated arrow keys | ||||
|    * ,-----------------------------------------------------------. | ||||
|    * |    |  |   |   |   |   |   |   |   |   |   |   |   |       | | ||||
|    * |-----------------------------------------------------------| | ||||
|    * |     |   |Up |   |   |   |   |   |   |   |   |   |   |     | | ||||
|    * |-----------------------------------------------------------| | ||||
|    * |       |Left|Down|Rght|   |   |   |   |   |   |   |   |    | | ||||
|    * |-----------------------------------------------------------| | ||||
|    * |        |   |   |   |   |   |   |   |   |   |   |          | | ||||
|    * |-----------------------------------------------------------| | ||||
|    * |    |    |    |                        |    |    |    |    | | ||||
|    * `-----------------------------------------------------------' | ||||
|    */ | ||||
| 	[_AL] = KEYMAP( | ||||
|         TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \ | ||||
|         TRNS,TRNS,UP,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \ | ||||
|         TRNS,LEFT,DOWN,RGHT,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \ | ||||
|         TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,   \ | ||||
|         TRNS,TRNS,TRNS,          TRNS,               TRNS,TRNS,TRNS,TRNS,TRNS), | ||||
| 
 | ||||
| 
 | ||||
|    /* 
 | ||||
|    * Primary function layer, mostly the same as the traditional Pok3r layout. | ||||
|    * ,-------------------------------------------------------------. | ||||
|    * |`~ | F1| F2| F3| F4| F5| F6| F7| F8| F9| F10| F11| F12|DEL   | | ||||
|    * |-------------------------------------------------------------| | ||||
|    * |    |_AL|   |   |  |  |Calc|PgUp|Up|PgDn|Ptscn|Srlck|Pause|  | | ||||
|    * |-------------------------------------------------------------| | ||||
|    * |      |   |   |   |   |   |Home|Left|Down|Rght|Ins|   |      | | ||||
|    * |-------------------------------------------------------------| | ||||
|    * |        |_UL|   |   |   |   |   |    |    |    |   |         | | ||||
|    * |-------------------------------------------------------------| | ||||
|    * |    |    |    |                          |    |    |    |    | | ||||
|    * `-------------------------------------------------------------' | ||||
|    */ | ||||
| 	[_FL] = KEYMAP( | ||||
|         GRAVE,F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12, DELETE, \ | ||||
|         TRNS,FN1,TRNS,TRNS,TRNS,TRNS,CALC,PGUP,UP,PGDN,PSCR,SLCK,PAUS,TRNS, \ | ||||
|         TRNS,MUTE,_VOLDOWN,_VOLUP,TRNS,TRNS,HOME,LEFT,DOWN,RGHT,INS,TRNS,TRNS,TRNS, \ | ||||
|         TRNS,TRNS,FN3,TRNS,TRNS,TRNS,TRNS,END,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \ | ||||
|         TRNS,TRNS,TRNS,          TRNS,               TRNS,TRNS,TRNS,TRNS,TRNS), | ||||
|     | ||||
|    /* 
 | ||||
|    * Locking layer for controlling the underglow. | ||||
|    *  | ||||
|    * ,-----------------------------------------------------------. | ||||
|    * |    |  |   |   |   |   |   |   |   |   |   |   |   |       | | ||||
|    * |-----------------------------------------------------------| | ||||
|    * |     |   |   |   |   |   |   |   |   |   |   |   |   |     | | ||||
|    * |-----------------------------------------------------------| | ||||
|    * |       |On|Mode|   |   |   |   |   |   |   |   |   |       | | ||||
|    * |-----------------------------------------------------------| | ||||
|    * |        |   |Hue+|Hue-|Sat+|Sat-|Val+|Val-|  |  |   |      | | ||||
|    * |-----------------------------------------------------------| | ||||
|    * |    |    |    |                        |    |    |    |    | | ||||
|    * `-----------------------------------------------------------' | ||||
|    */ | ||||
| 	[_UL] = KEYMAP( | ||||
|         TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \ | ||||
|         TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \ | ||||
|         TRNS,FN4,FN5,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \ | ||||
|         TRNS,TRNS,TRNS,FN6,FN7,FN8,FN9,FN10,FN11,TRNS,TRNS,TRNS,TRNS,TRNS,   \ | ||||
|         TRNS,TRNS,TRNS,          TRNS,               TRNS,TRNS,TRNS,TRNS,TRNS), | ||||
| }; | ||||
| 
 | ||||
| enum function_id { | ||||
|     RGBLED_TOGGLE, | ||||
|     RGBLED_STEP_MODE, | ||||
|     RGBLED_INCREASE_HUE, | ||||
|     RGBLED_DECREASE_HUE, | ||||
|     RGBLED_INCREASE_SAT, | ||||
|     RGBLED_DECREASE_SAT, | ||||
|     RGBLED_INCREASE_VAL, | ||||
|     RGBLED_DECREASE_VAL, | ||||
|     SHIFT_ESC, | ||||
| }; | ||||
| 
 | ||||
| const uint16_t PROGMEM fn_actions[] = { | ||||
|     [0]  = ACTION_LAYER_MOMENTARY(2),  // Momentary Fn overlay
 | ||||
|     [1]  = ACTION_LAYER_TOGGLE(1),     // Toggle Arrow Layer overlay
 | ||||
|     [2]  = ACTION_LAYER_TAP_KEY(2, KC_CAPS), // Tap to toggle caps lock and hold to activate function layer
 | ||||
|     [3]  = ACTION_LAYER_TOGGLE(3),     // Toggle Underglow Layer overlay
 | ||||
|     [4]  = ACTION_FUNCTION(RGBLED_TOGGLE), //Turn on/off underglow
 | ||||
|     [5]  = ACTION_FUNCTION(RGBLED_STEP_MODE), // Change underglow mode
 | ||||
|     [6]  = ACTION_FUNCTION(RGBLED_INCREASE_HUE), | ||||
|     [7]  = ACTION_FUNCTION(RGBLED_DECREASE_HUE), | ||||
|     [8]  = ACTION_FUNCTION(RGBLED_INCREASE_SAT), | ||||
|     [9]  = ACTION_FUNCTION(RGBLED_DECREASE_SAT), | ||||
|     [10] = ACTION_FUNCTION(RGBLED_INCREASE_VAL), | ||||
|     [11] = ACTION_FUNCTION(RGBLED_DECREASE_VAL), | ||||
|     [12] = ACTION_FUNCTION(SHIFT_ESC), | ||||
| }; | ||||
| 
 | ||||
| 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) { | ||||
|             register_code(KC_RSFT); | ||||
|           } else { | ||||
|             unregister_code(KC_RSFT); | ||||
|           } | ||||
|         break; | ||||
|       } | ||||
|     return MACRO_NONE; | ||||
| }; | ||||
| 
 | ||||
| void matrix_scan_user(void) { | ||||
| 
 | ||||
| // Layer LED indicators
 | ||||
| // ESC led on when in function layer, WASD cluster leds enabled when on arrow cluster
 | ||||
|     uint32_t layer = layer_state; | ||||
|     if (layer & (1<<1)) { | ||||
|         gh60_wasd_leds_on(); | ||||
|     } else { | ||||
|         gh60_wasd_leds_off(); | ||||
|     } | ||||
| 
 | ||||
|     if (layer & (1<<2)) { | ||||
|         gh60_esc_led_on(); | ||||
|     } else { | ||||
|         gh60_esc_led_off(); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| #define MODS_CTRL_MASK  (MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT)) | ||||
| 
 | ||||
| void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { | ||||
|   switch (id) { | ||||
|     case RGBLED_TOGGLE: | ||||
|       //led operations
 | ||||
|       if (record->event.pressed) { | ||||
|         rgblight_toggle(); | ||||
|         } | ||||
|         break; | ||||
|     case RGBLED_INCREASE_HUE: | ||||
|       if (record->event.pressed) { | ||||
|         rgblight_increase_hue(); | ||||
|         } | ||||
|         break; | ||||
|     case RGBLED_DECREASE_HUE: | ||||
|       if (record->event.pressed) { | ||||
|         rgblight_decrease_hue(); | ||||
|         } | ||||
|         break; | ||||
|     case RGBLED_INCREASE_SAT: | ||||
|       if (record->event.pressed) { | ||||
|         rgblight_increase_sat(); | ||||
|         } | ||||
|         break; | ||||
|     case RGBLED_DECREASE_SAT: | ||||
|       if (record->event.pressed) { | ||||
|         rgblight_decrease_sat(); | ||||
|         } | ||||
|         break; | ||||
|     case RGBLED_INCREASE_VAL: | ||||
|         if (record->event.pressed) { | ||||
|           rgblight_increase_val(); | ||||
|         } | ||||
|         break; | ||||
|     case RGBLED_DECREASE_VAL: | ||||
|         if (record->event.pressed) { | ||||
|           rgblight_decrease_val(); | ||||
|         } | ||||
|         break; | ||||
|     case RGBLED_STEP_MODE: | ||||
|         if (record->event.pressed) { | ||||
|           rgblight_step(); | ||||
|         } | ||||
|         break; | ||||
|     static uint8_t shift_esc_shift_mask; | ||||
|     // Shift + ESC = ~
 | ||||
|     case SHIFT_ESC: | ||||
|       shift_esc_shift_mask = get_mods()&MODS_CTRL_MASK; | ||||
|       if (record->event.pressed) { | ||||
|         if (shift_esc_shift_mask) { | ||||
|           add_key(KC_GRV); | ||||
|           send_keyboard_report(); | ||||
|         } else { | ||||
|           add_key(KC_ESC); | ||||
|           send_keyboard_report(); | ||||
|         } | ||||
|       } else { | ||||
|         if (shift_esc_shift_mask) { | ||||
|           del_key(KC_GRV); | ||||
|           send_keyboard_report(); | ||||
|         } else { | ||||
|           del_key(KC_ESC); | ||||
|           send_keyboard_report(); | ||||
|         } | ||||
|       } | ||||
|       break; | ||||
|     } | ||||
| }; | ||||
| @ -0,0 +1,16 @@ | ||||
| robotmaxtron's GH60 Layout | ||||
| ===================== | ||||
| 
 | ||||
| ##Quantum MK Firmware | ||||
| For the full Quantum feature list, see the parent readme.md. | ||||
| 
 | ||||
| * Standard ANSI layout with Pok3r styled function layers | ||||
| * ESC key led enables when on function layer | ||||
| * Lockable layer with arrow keys on WASD with backlighting to indicate locked on arrow layer | ||||
| * Neopixel/WS2812 RGB Underglow Support | ||||
| 
 | ||||
| ## Reference Images | ||||
| ![Wiring Refererence] (WS2812-wiring.jpg) | ||||
| 
 | ||||
| ### Additional Credits | ||||
| Keymap has been based on various keymaps available from the QMK Repo for the GH60-SATAN and KC60 keyboards. | ||||
| @ -0,0 +1 @@ | ||||
| HHKB_JP=yes | ||||
| @ -0,0 +1,58 @@ | ||||
| #include "hhkb.h" | ||||
| 
 | ||||
| #define _______ KC_TRNS | ||||
| 
 | ||||
| 
 | ||||
| /* Layer 0: HHKB JP
 | ||||
|  * ,-----------------------------------------------------------. | ||||
|  * |Esc|  1|  2|  3|  4|  5|  6|  7|  8|  9| 10|  -|  =|Yen|Bsp| | ||||
|  * |-----------------------------------------------------------| | ||||
|  * |Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|     | | ||||
|  * |------------------------------------------------------` Ent| | ||||
|  * |Ctrl  |  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;|  '|  `|    | | ||||
|  * |-----------------------------------------------------------| | ||||
|  * |Shft   |  Z|  X|  C|  V|  B|  N|  M|  ,|  .|  /|  \| Up|Sft| | ||||
|  * |-----------------------------------------------------------| | ||||
|  * |   ||Ctl|Alt|Cmd|   |   Spc   |Bsp|   |   |   ||Lft|Dwn|Rgh| | ||||
|  * `-----------------------------------------------------------' | ||||
|  */ | ||||
| 
 | ||||
| /* Layer 1: HHKB mode (HHKB Fn)
 | ||||
|  * ,-----------------------------------------------------------. | ||||
|  * |Pwr| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del| | ||||
|  * |-----------------------------------------------------------| | ||||
|  * |Caps |   |   |   |   |   |   |   |Psc|Slk|Pus|Up |   |     | | ||||
|  * |------------------------------------------------------`    | | ||||
|  * |      |VoD|VoU|Mut|   |   |  *|  /|Hom|PgU|Lef|Rig|   |    | | ||||
|  * |-----------------------------------------------------------| | ||||
|  * |       |   |   |   |   |   |  +|  -|End|PgD|Dow|   |   |   | | ||||
|  * |-----------------------------------------------------------| | ||||
|  * |   ||   |   |   |   |         |   |   |   |   ||   |   |   | | ||||
|  * `-----------------------------------------------------------' | ||||
|  */ | ||||
| 
 | ||||
| const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | ||||
|   [0] = KEYMAP_JP( | ||||
|     KC_ESC,   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_JYEN,  KC_BSPC, | ||||
|     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_LCTL,  KC_A,    KC_S,    KC_D,    KC_F,     KC_G,    KC_H,    KC_J,     KC_K,    KC_L, KC_SCLN, KC_QUOT, KC_BSLS, KC_ENT, | ||||
|     KC_LSFT,  KC_Z,    KC_X,    KC_C,    KC_V,     KC_B,    KC_N,    KC_M,  KC_COMM,  KC_DOT, KC_SLSH,   KC_RO,   KC_UP, KC_RSFT, | ||||
|     MO(1), KC_ZKHK, KC_LGUI, KC_LALT, KC_MHEN,         KC_SPC,    KC_HENK,  KC_KANA, KC_RALT,   MO(1), KC_LEFT, KC_DOWN, KC_RGHT | ||||
|   ), | ||||
| 
 | ||||
|   [1] = KEYMAP_JP( | ||||
|     KC_PWR,    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_INS,  KC_DEL, | ||||
|     KC_CAPS, _______, _______, _______, _______, _______, _______, _______, KC_PSCR, KC_SLCK, KC_PAUS,   KC_UP, _______, | ||||
|     _______, KC_VOLD, KC_VOLU, KC_MUTE,  KC_PWR, _______, KC_PAST, KC_PSLS, KC_HOME, KC_PGUP, KC_LEFT, KC_RGHT, _______, KC_PENT, | ||||
|     _______, _______, _______, _______, _______, _______, KC_PPLS, KC_PMNS,  KC_END, KC_PGDN, KC_DOWN, _______, _______, _______, | ||||
|     _______, _______, _______, _______, _______,     _______     , _______, _______, _______, _______, _______, _______, _______ | ||||
|   ) | ||||
| }; | ||||
| 
 | ||||
| const macro_t *action_get_macro(keyrecord_t *record, uint8_t macro_id, uint8_t opt) { | ||||
|   return MACRO_NONE; | ||||
| } | ||||
| 
 | ||||
| const uint16_t PROGMEM fn_actions[] = { | ||||
| 
 | ||||
| }; | ||||
| @ -0,0 +1 @@ | ||||
| HHKB_JP=yes | ||||
| @ -0,0 +1,65 @@ | ||||
| #include "hhkb.h" | ||||
| 
 | ||||
| #define _______ KC_TRNS | ||||
| 
 | ||||
| enum { | ||||
|   ZER, | ||||
|   HDN, | ||||
|   OSY | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| #define CTL_ESC CTL_T(KC_ESC) | ||||
| #define SFT_BSP SFT_T(KC_BSPC) | ||||
| 
 | ||||
| #define SCRNS3 LGUI(LCTL(LSFT(KC_3))) | ||||
| #define SCRNS4 LGUI(LCTL(LSFT(KC_4))) | ||||
| 
 | ||||
| 
 | ||||
| /* hhkb jp ~ layout
 | ||||
|  * ,-----------------------------------------------------------. | ||||
|  * |Esc|  1|  2|  3|  4|  5|  6|  7|  8|  9| 10|  -|  =|Yen|Bsp| | ||||
|  * |-----------------------------------------------------------| | ||||
|  * |Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|     | | ||||
|  * |------------------------------------------------------` Ent| | ||||
|  * |Ctrl  |  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;|  '|  `|    | | ||||
|  * |-----------------------------------------------------------| | ||||
|  * |Shft   |  Z|  X|  C|  V|  B|  N|  M|  ,|  .|  /|  \| Up|Sft| | ||||
|  * |-----------------------------------------------------------| | ||||
|  * |   ||Ctl|Alt|Cmd|   |   Spc   |Bsp|   |   |   ||Lft|Dwn|Rgh| | ||||
|  * `-----------------------------------------------------------' | ||||
|  */ | ||||
| 
 | ||||
| const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | ||||
|   [ZER] = KEYMAP_JP( | ||||
|     KC_ESC,   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_INS,  KC_BSPC, | ||||
|     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, | ||||
|     CTL_ESC,  KC_A,    KC_S,    KC_D,    KC_F,     KC_G,    KC_H,    KC_J,     KC_K,    KC_L, KC_SCLN, KC_QUOT,  KC_GRV, KC_ENT, | ||||
|     KC_LSFT,  KC_Z,    KC_X,    KC_C,    KC_V,     KC_B,    KC_N,    KC_M,  KC_COMM,  KC_DOT, KC_SLSH, KC_BSLS,   KC_UP, KC_RSFT, | ||||
|     MO(HDN),  KC_LCTL, KC_LALT, KC_LGUI, MO(HDN),      KC_SPC,    SFT_BSP,  MO(HDN), MO(OSY),   KC_NO, KC_LEFT, KC_DOWN, KC_RGHT | ||||
|   ), | ||||
| 
 | ||||
|   [HDN] = KEYMAP_JP( | ||||
|     KC_GRV,    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_DEL, | ||||
|     _______, KC_EXLM,   KC_AT, KC_HASH,  KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, _______, _______, | ||||
|     _______, KC_TILD,  KC_GRV, KC_BSLS, KC_PIPE, KC_MINS, KC_LEFT, KC_DOWN,   KC_UP, KC_RGHT, KC_TILD,  KC_GRV, _______, _______, | ||||
|     _______, KC_VOLD, KC_VOLU, KC_MUTE,  KC_PWR, _______, _______,  KC_ENT, _______, _______, _______, _______, KC_PGUP, _______, | ||||
|     _______, _______, _______, _______, _______,     KC_UNDS     ,  KC_DEL, _______, _______, _______, KC_HOME, KC_PGDN, KC_END | ||||
|   ), | ||||
| 
 | ||||
|   [OSY] = KEYMAP_JP( | ||||
|     _______, _______, _______,  SCRNS3,  SCRNS4, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, | ||||
|     _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, | ||||
|     _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, | ||||
|     _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, | ||||
|     _______, _______, _______, _______, _______,      _______    , _______, _______, _______, _______, _______, _______, _______ | ||||
|   ) | ||||
| }; | ||||
| 
 | ||||
| const macro_t *action_get_macro(keyrecord_t *record, uint8_t macro_id, uint8_t opt) { | ||||
|   return MACRO_NONE; | ||||
| } | ||||
| 
 | ||||
| const uint16_t PROGMEM fn_actions[] = { | ||||
| 
 | ||||
| }; | ||||
| @ -0,0 +1,113 @@ | ||||
| /*
 | ||||
| Copyright 2016 Fred Sundvik <fsundvik@gmail.com> | ||||
| 
 | ||||
| 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/>.
 | ||||
| */ | ||||
| 
 | ||||
| #ifndef _GDISP_LLD_BOARD_H | ||||
| #define _GDISP_LLD_BOARD_H | ||||
| 
 | ||||
| static const I2CConfig i2ccfg = { | ||||
|   400000 // clock speed (Hz); 400kHz max for IS31
 | ||||
| }; | ||||
| 
 | ||||
| #define GDISP_SCREEN_WIDTH  7 | ||||
| #define GDISP_SCREEN_HEIGHT 7 | ||||
| 
 | ||||
| static const uint8_t led_mask[] = { | ||||
| 	0xFF, 0x00, /* C1-1 -> C1-16 */ | ||||
| 	0xFF, 0x00, /* C2-1 -> C2-16 */ | ||||
| 	0xFF, 0x00, /* C3-1 -> C3-16 */ | ||||
| 	0xFF, 0x00, /* C4-1 -> C4-16 */ | ||||
| 	0x3F, 0x00, /* C5-1 -> C5-16 */ | ||||
| 	0x00, 0x00, /* C6-1 -> C6-16 */ | ||||
| 	0x00, 0x00, /* C7-1 -> C7-16 */ | ||||
| 	0x00, 0x00, /* C8-1 -> C8-16 */ | ||||
| 	0x00, 0x00, /* C9-1 -> C9-16 */ | ||||
| }; | ||||
| 
 | ||||
| // The address of the LED
 | ||||
| #define LA(c, r) (c + r * 16 ) | ||||
| // Need to be an address that is not mapped, but inside the range of the controller matrix
 | ||||
| #define NA LA(8, 8) | ||||
| 
 | ||||
| // The numbers in the comments are the led numbers DXX on the PCB
 | ||||
| // The mapping is taken from the schematic of left hand side
 | ||||
| static const uint8_t led_mapping[GDISP_SCREEN_HEIGHT][GDISP_SCREEN_WIDTH] = { | ||||
| //   45        44        43        42        41        40        39
 | ||||
|    { LA(1, 1), LA(1, 0), LA(0, 4), LA(0, 3), LA(0, 2), LA(0, 1), LA(0, 0)}, | ||||
| //   52        51        50        49        48        47        46
 | ||||
|    { LA(2, 3), LA(2, 2), LA(2, 1), LA(2, 0), LA(1, 4), LA(1, 3), LA(1, 2) }, | ||||
| //   58        57        56        55        54        53        N/A
 | ||||
|    { LA(3, 4), LA(3, 3), LA(3, 2), LA(3, 1), LA(3, 0), LA(2, 4), NA }, | ||||
| //   67        66        65        64        63        62        61
 | ||||
|    { LA(5, 3), LA(5, 2), LA(5, 1), LA(5, 0), LA(4, 4), LA(4, 3), LA(4, 2) }, | ||||
| //   76        75        74        73        72        60        59
 | ||||
|    { LA(7, 3), LA(7, 2), LA(7, 1), LA(7, 0), LA(6, 3), LA(4, 1), LA(4, 0) }, | ||||
| //   N/A       N/A       N/A       N/A       N/A       N/A       68
 | ||||
|    { NA,       NA,       NA,       NA,       NA,       NA,       LA(5, 4) }, | ||||
| //   N/A       N/A       N/A       N/A       71        70        69
 | ||||
|    { NA,       NA,       NA,       NA,       LA(6, 2), LA(6, 1), LA(6, 0) }, | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| #define IS31_ADDR_DEFAULT 0x74 // AD connected to GND
 | ||||
| #define IS31_TIMEOUT 5000 | ||||
| 
 | ||||
| static GFXINLINE void init_board(GDisplay *g) { | ||||
|     (void) g; | ||||
|     /* I2C pins */ | ||||
|     palSetPadMode(GPIOB, 0, PAL_MODE_ALTERNATIVE_2); // PTB0/I2C0/SCL
 | ||||
|     palSetPadMode(GPIOB, 1, PAL_MODE_ALTERNATIVE_2); // PTB1/I2C0/SDA
 | ||||
|     palSetPadMode(GPIOB, 16, PAL_MODE_OUTPUT_PUSHPULL); | ||||
|     palClearPad(GPIOB, 16); | ||||
|     /* start I2C */ | ||||
|     i2cStart(&I2CD1, &i2ccfg); | ||||
|     // try high drive (from kiibohd)
 | ||||
|     I2CD1.i2c->C2 |= I2Cx_C2_HDRS; | ||||
|     // try glitch fixing (from kiibohd)
 | ||||
|     I2CD1.i2c->FLT = 4; | ||||
| } | ||||
| 
 | ||||
| static GFXINLINE void post_init_board(GDisplay *g) { | ||||
| 	(void) g; | ||||
| } | ||||
| 
 | ||||
| static GFXINLINE const uint8_t* get_led_mask(GDisplay* g) { | ||||
|     (void) g; | ||||
|     return led_mask; | ||||
| } | ||||
| 
 | ||||
| static GFXINLINE uint8_t get_led_address(GDisplay* g, uint16_t x, uint16_t y) | ||||
| { | ||||
|     (void) g; | ||||
|     return led_mapping[y][x]; | ||||
| } | ||||
| 
 | ||||
| static GFXINLINE void set_hardware_shutdown(GDisplay* g, bool shutdown) { | ||||
|     (void) g; | ||||
|     if(!shutdown) { | ||||
|         palSetPad(GPIOB, 16); | ||||
|     } | ||||
|     else { | ||||
|         palClearPad(GPIOB, 16); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static GFXINLINE void write_data(GDisplay *g, uint8_t* data, uint16_t length) { | ||||
| 	(void) g; | ||||
| 	i2cMasterTransmitTimeout(&I2CD1, IS31_ADDR_DEFAULT, data, length, 0, 0, US2ST(IS31_TIMEOUT)); | ||||
| } | ||||
| 
 | ||||
| #endif /* _GDISP_LLD_BOARD_H */ | ||||
| @ -0,0 +1,2 @@ | ||||
| GFXINC += drivers/gdisp/IS31FL3731C | ||||
| GFXSRC += drivers/gdisp/IS31FL3731C/gdisp_IS31FL3731C.c | ||||
| @ -0,0 +1,333 @@ | ||||
| /*
 | ||||
| Copyright 2016 Fred Sundvik <fsundvik@gmail.com> | ||||
| 
 | ||||
| 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 "gfx.h" | ||||
| 
 | ||||
| #if GFX_USE_GDISP | ||||
| 
 | ||||
| #define GDISP_DRIVER_VMT			GDISPVMT_IS31FL3731C_ERGODOX | ||||
| #include "drivers/gdisp/IS31FL3731C/gdisp_lld_config.h" | ||||
| #include "src/gdisp/gdisp_driver.h" | ||||
| 
 | ||||
| #include "board_IS31FL3731C.h" | ||||
| 
 | ||||
| /*===========================================================================*/ | ||||
| /* Driver local definitions.                                                 */ | ||||
| /*===========================================================================*/ | ||||
| 
 | ||||
| #ifndef GDISP_SCREEN_HEIGHT | ||||
| 	#define GDISP_SCREEN_HEIGHT		9 | ||||
| #endif | ||||
| #ifndef GDISP_SCREEN_WIDTH | ||||
| 	#define GDISP_SCREEN_WIDTH		16 | ||||
| #endif | ||||
| #ifndef GDISP_INITIAL_CONTRAST | ||||
| 	#define GDISP_INITIAL_CONTRAST	0 | ||||
| #endif | ||||
| #ifndef GDISP_INITIAL_BACKLIGHT | ||||
| 	#define GDISP_INITIAL_BACKLIGHT	100 | ||||
| #endif | ||||
| 
 | ||||
| #define GDISP_FLG_NEEDFLUSH			(GDISP_FLG_DRIVER<<0) | ||||
| 
 | ||||
| #define IS31_ADDR_DEFAULT 0x74 | ||||
| 
 | ||||
| #define IS31_REG_CONFIG  0x00 | ||||
| // bits in reg
 | ||||
| #define IS31_REG_CONFIG_PICTUREMODE 0x00 | ||||
| #define IS31_REG_CONFIG_AUTOPLAYMODE 0x08 | ||||
| #define IS31_REG_CONFIG_AUDIOPLAYMODE 0x18 | ||||
| // D2:D0 bits are starting frame for autoplay mode
 | ||||
| 
 | ||||
| #define IS31_REG_PICTDISP 0x01 // D2:D0 frame select for picture mode
 | ||||
| 
 | ||||
| #define IS31_REG_AUTOPLAYCTRL1 0x02 | ||||
| // D6:D4 number of loops (000=infty)
 | ||||
| // D2:D0 number of frames to be used
 | ||||
| 
 | ||||
| #define IS31_REG_AUTOPLAYCTRL2 0x03 // D5:D0 delay time (*11ms)
 | ||||
| 
 | ||||
| #define IS31_REG_DISPLAYOPT 0x05 | ||||
| #define IS31_REG_DISPLAYOPT_INTENSITY_SAME 0x20 // same intensity for all frames
 | ||||
| #define IS31_REG_DISPLAYOPT_BLINK_ENABLE 0x8 | ||||
| // D2:D0 bits blink period time (*0.27s)
 | ||||
| 
 | ||||
| #define IS31_REG_AUDIOSYNC 0x06 | ||||
| #define IS31_REG_AUDIOSYNC_ENABLE 0x1 | ||||
| 
 | ||||
| #define IS31_REG_FRAMESTATE 0x07 | ||||
| 
 | ||||
| #define IS31_REG_BREATHCTRL1 0x08 | ||||
| // D6:D4 fade out time (26ms*2^i)
 | ||||
| // D2:D0 fade in time (26ms*2^i)
 | ||||
| 
 | ||||
| #define IS31_REG_BREATHCTRL2 0x09 | ||||
| #define IS31_REG_BREATHCTRL2_ENABLE 0x10 | ||||
| // D2:D0 extinguish time (3.5ms*2^i)
 | ||||
| 
 | ||||
| #define IS31_REG_SHUTDOWN 0x0A | ||||
| #define IS31_REG_SHUTDOWN_OFF 0x0 | ||||
| #define IS31_REG_SHUTDOWN_ON 0x1 | ||||
| 
 | ||||
| #define IS31_REG_AGCCTRL 0x0B | ||||
| #define IS31_REG_ADCRATE 0x0C | ||||
| 
 | ||||
| #define IS31_COMMANDREGISTER 0xFD | ||||
| #define IS31_FUNCTIONREG 0x0B    // helpfully called 'page nine'
 | ||||
| #define IS31_FUNCTIONREG_SIZE 0xD | ||||
| 
 | ||||
| #define IS31_FRAME_SIZE 0xB4 | ||||
| 
 | ||||
| #define IS31_PWM_REG 0x24 | ||||
| #define IS31_PWM_SIZE 0x90 | ||||
| 
 | ||||
| #define IS31_LED_MASK_SIZE 0x12 | ||||
| #define IS31_SCREEN_WIDTH 16 | ||||
| 
 | ||||
| #define IS31 | ||||
| 
 | ||||
| //Generated by http://jared.geek.nz/2013/feb/linear-led-pwm
 | ||||
| const unsigned char cie[256] = { | ||||
|     0, 0, 0, 0, 0, 1, 1, 1, 1, 1, | ||||
|     1, 1, 1, 1, 2, 2, 2, 2, 2, 2, | ||||
|     2, 2, 2, 3, 3, 3, 3, 3, 3, 3, | ||||
|     3, 4, 4, 4, 4, 4, 4, 5, 5, 5, | ||||
|     5, 5, 6, 6, 6, 6, 6, 7, 7, 7, | ||||
|     7, 8, 8, 8, 8, 9, 9, 9, 10, 10, | ||||
|     10, 10, 11, 11, 11, 12, 12, 12, 13, 13, | ||||
|     13, 14, 14, 15, 15, 15, 16, 16, 17, 17, | ||||
|     17, 18, 18, 19, 19, 20, 20, 21, 21, 22, | ||||
|     22, 23, 23, 24, 24, 25, 25, 26, 26, 27, | ||||
|     28, 28, 29, 29, 30, 31, 31, 32, 32, 33, | ||||
|     34, 34, 35, 36, 37, 37, 38, 39, 39, 40, | ||||
|     41, 42, 43, 43, 44, 45, 46, 47, 47, 48, | ||||
|     49, 50, 51, 52, 53, 54, 54, 55, 56, 57, | ||||
|     58, 59, 60, 61, 62, 63, 64, 65, 66, 67, | ||||
|     68, 70, 71, 72, 73, 74, 75, 76, 77, 79, | ||||
|     80, 81, 82, 83, 85, 86, 87, 88, 90, 91, | ||||
|     92, 94, 95, 96, 98, 99, 100, 102, 103, 105, | ||||
|     106, 108, 109, 110, 112, 113, 115, 116, 118, 120, | ||||
|     121, 123, 124, 126, 128, 129, 131, 132, 134, 136, | ||||
|     138, 139, 141, 143, 145, 146, 148, 150, 152, 154, | ||||
|     155, 157, 159, 161, 163, 165, 167, 169, 171, 173, | ||||
|     175, 177, 179, 181, 183, 185, 187, 189, 191, 193, | ||||
|     196, 198, 200, 202, 204, 207, 209, 211, 214, 216, | ||||
|     218, 220, 223, 225, 228, 230, 232, 235, 237, 240, | ||||
|     242, 245, 247, 250, 252, 255, | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| /*===========================================================================*/ | ||||
| /* Driver local functions.                                                   */ | ||||
| /*===========================================================================*/ | ||||
| 
 | ||||
| typedef struct{ | ||||
|     uint8_t write_buffer_offset; | ||||
|     uint8_t write_buffer[IS31_FRAME_SIZE]; | ||||
|     uint8_t frame_buffer[GDISP_SCREEN_HEIGHT * GDISP_SCREEN_WIDTH]; | ||||
|     uint8_t page; | ||||
| }__attribute__((__packed__)) PrivData; | ||||
| 
 | ||||
| // Some common routines and macros
 | ||||
| #define PRIV(g)                         ((PrivData*)g->priv) | ||||
| 
 | ||||
| /*===========================================================================*/ | ||||
| /* Driver exported functions.                                                */ | ||||
| /*===========================================================================*/ | ||||
| 
 | ||||
| static GFXINLINE void write_page(GDisplay* g, uint8_t page) { | ||||
|     uint8_t tx[2] __attribute__((aligned(2))); | ||||
|     tx[0] = IS31_COMMANDREGISTER; | ||||
|     tx[1] = page; | ||||
|     write_data(g, tx, 2); | ||||
| } | ||||
| 
 | ||||
| static GFXINLINE void write_register(GDisplay* g, uint8_t page, uint8_t reg, uint8_t data) { | ||||
|     uint8_t tx[2] __attribute__((aligned(2))); | ||||
|     tx[0] = reg; | ||||
|     tx[1] = data; | ||||
|     write_page(g, page); | ||||
|     write_data(g, tx, 2); | ||||
| } | ||||
| 
 | ||||
| static GFXINLINE void write_ram(GDisplay *g, uint8_t page, uint16_t offset, uint16_t length) { | ||||
|     PRIV(g)->write_buffer_offset = offset; | ||||
|     write_page(g, page); | ||||
|     write_data(g, (uint8_t*)PRIV(g), length + 1); | ||||
| } | ||||
| 
 | ||||
| LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { | ||||
| 	// The private area is the display surface.
 | ||||
| 	g->priv = gfxAlloc(sizeof(PrivData)); | ||||
|     __builtin_memset(PRIV(g), 0, sizeof(PrivData)); | ||||
| 	PRIV(g)->page = 0; | ||||
| 
 | ||||
| 	// Initialise the board interface
 | ||||
| 	init_board(g); | ||||
| 	gfxSleepMilliseconds(10); | ||||
| 
 | ||||
|     // zero function page, all registers (assuming full_page is all zeroes)
 | ||||
|     write_ram(g, IS31_FUNCTIONREG, 0, IS31_FUNCTIONREG_SIZE); | ||||
|     set_hardware_shutdown(g, false); | ||||
|     gfxSleepMilliseconds(10); | ||||
|     // software shutdown
 | ||||
|     write_register(g, IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_OFF); | ||||
|     gfxSleepMilliseconds(10); | ||||
|     // zero function page, all registers
 | ||||
|     write_ram(g, IS31_FUNCTIONREG, 0, IS31_FUNCTIONREG_SIZE); | ||||
|     gfxSleepMilliseconds(10); | ||||
| 
 | ||||
| 
 | ||||
|     // zero all LED registers on all 8 pages, and enable the mask
 | ||||
|     __builtin_memcpy(PRIV(g)->write_buffer, get_led_mask(g), IS31_LED_MASK_SIZE); | ||||
|     for(uint8_t i=0; i<8; i++) { | ||||
|         write_ram(g, i, 0, IS31_FRAME_SIZE); | ||||
|         gfxSleepMilliseconds(1); | ||||
|     } | ||||
| 
 | ||||
|     // software shutdown disable (i.e. turn stuff on)
 | ||||
|     write_register(g, IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_ON); | ||||
|     gfxSleepMilliseconds(10); | ||||
| 
 | ||||
|     // Finish Init
 | ||||
|     post_init_board(g); | ||||
| 
 | ||||
| 	/* Initialise the GDISP structure */ | ||||
| 	g->g.Width = GDISP_SCREEN_WIDTH; | ||||
| 	g->g.Height = GDISP_SCREEN_HEIGHT; | ||||
| 	g->g.Orientation = GDISP_ROTATE_0; | ||||
| 	g->g.Powermode = powerOn; | ||||
| 	g->g.Backlight = GDISP_INITIAL_BACKLIGHT; | ||||
| 	g->g.Contrast = GDISP_INITIAL_CONTRAST; | ||||
| 	return TRUE; | ||||
| } | ||||
| 
 | ||||
| #if GDISP_HARDWARE_FLUSH | ||||
| 	LLDSPEC void gdisp_lld_flush(GDisplay *g) { | ||||
| 		// Don't flush if we don't need it.
 | ||||
| 		if (!(g->flags & GDISP_FLG_NEEDFLUSH)) | ||||
| 			return; | ||||
| 
 | ||||
| 		PRIV(g)->page++; | ||||
| 		PRIV(g)->page %= 2; | ||||
| 		// TODO: some smarter algorithm for this
 | ||||
| 		// We should run only one physical page at a time
 | ||||
| 		// This way we don't need to send so much data, and
 | ||||
| 		// we could use slightly less memory
 | ||||
| 		uint8_t* src = PRIV(g)->frame_buffer; | ||||
| 		for (int y=0;y<GDISP_SCREEN_HEIGHT;y++) { | ||||
| 		    for (int x=0;x<GDISP_SCREEN_WIDTH;x++) { | ||||
| 		        PRIV(g)->write_buffer[get_led_address(g, x, y)]=cie[*src]; | ||||
| 		        ++src; | ||||
| 		    } | ||||
| 		} | ||||
|         write_ram(g, PRIV(g)->page, IS31_PWM_REG, IS31_PWM_SIZE); | ||||
|         gfxSleepMilliseconds(1); | ||||
|         write_register(g, IS31_FUNCTIONREG, IS31_REG_PICTDISP, PRIV(g)->page); | ||||
| 
 | ||||
| 		g->flags &= ~GDISP_FLG_NEEDFLUSH; | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| #if GDISP_HARDWARE_DRAWPIXEL | ||||
| 	LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) { | ||||
| 		coord_t		x, y; | ||||
| 
 | ||||
| 		switch(g->g.Orientation) { | ||||
| 		default: | ||||
| 		case GDISP_ROTATE_0: | ||||
| 			x = g->p.x; | ||||
| 			y = g->p.y; | ||||
| 			break; | ||||
| 		case GDISP_ROTATE_180: | ||||
| 			x = GDISP_SCREEN_WIDTH-1 - g->p.x; | ||||
| 			y = g->p.y; | ||||
| 			break; | ||||
| 		} | ||||
| 		PRIV(g)->frame_buffer[y * GDISP_SCREEN_WIDTH + x] = gdispColor2Native(g->p.color); | ||||
| 		g->flags |= GDISP_FLG_NEEDFLUSH; | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| #if GDISP_HARDWARE_PIXELREAD | ||||
| 	LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) { | ||||
| 		coord_t		x, y; | ||||
| 
 | ||||
| 		switch(g->g.Orientation) { | ||||
| 		default: | ||||
| 		case GDISP_ROTATE_0: | ||||
| 			x = g->p.x; | ||||
| 			y = g->p.y; | ||||
| 			break; | ||||
| 		case GDISP_ROTATE_180: | ||||
| 			x = GDISP_SCREEN_WIDTH-1 - g->p.x; | ||||
| 			y = g->p.y; | ||||
| 			break; | ||||
| 		} | ||||
| 		return gdispNative2Color(PRIV(g)->frame_buffer[y * GDISP_SCREEN_WIDTH + x]); | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| #if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL | ||||
| 	LLDSPEC void gdisp_lld_control(GDisplay *g) { | ||||
| 		switch(g->p.x) { | ||||
| 		case GDISP_CONTROL_POWER: | ||||
| 			if (g->g.Powermode == (powermode_t)g->p.ptr) | ||||
| 				return; | ||||
| 			switch((powermode_t)g->p.ptr) { | ||||
| 			case powerOff: | ||||
| 			case powerSleep: | ||||
| 			case powerDeepSleep: | ||||
|                 write_register(g, IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_OFF); | ||||
| 				break; | ||||
| 			case powerOn: | ||||
|                 write_register(g, IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, IS31_REG_SHUTDOWN_ON); | ||||
| 				break; | ||||
| 			default: | ||||
| 				return; | ||||
| 			} | ||||
| 			g->g.Powermode = (powermode_t)g->p.ptr; | ||||
| 			return; | ||||
| 
 | ||||
| 		case GDISP_CONTROL_ORIENTATION: | ||||
| 			if (g->g.Orientation == (orientation_t)g->p.ptr) | ||||
| 				return; | ||||
| 			switch((orientation_t)g->p.ptr) { | ||||
| 			/* Rotation is handled by the drawing routines */ | ||||
| 			case GDISP_ROTATE_0: | ||||
| 			case GDISP_ROTATE_180: | ||||
| 				g->g.Height = GDISP_SCREEN_HEIGHT; | ||||
| 				g->g.Width = GDISP_SCREEN_WIDTH; | ||||
| 				break; | ||||
| 			case GDISP_ROTATE_90: | ||||
| 			case GDISP_ROTATE_270: | ||||
| 				g->g.Height = GDISP_SCREEN_WIDTH; | ||||
| 				g->g.Width = GDISP_SCREEN_HEIGHT; | ||||
| 				break; | ||||
| 			default: | ||||
| 				return; | ||||
| 			} | ||||
| 			g->g.Orientation = (orientation_t)g->p.ptr; | ||||
| 			return; | ||||
| 
 | ||||
| 		case GDISP_CONTROL_CONTRAST: | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| #endif // GDISP_NEED_CONTROL
 | ||||
| 
 | ||||
| #endif // GFX_USE_GDISP
 | ||||
| @ -0,0 +1,36 @@ | ||||
| /*
 | ||||
| Copyright 2016 Fred Sundvik <fsundvik@gmail.com> | ||||
| 
 | ||||
| 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/>.
 | ||||
| */ | ||||
| 
 | ||||
| #ifndef _GDISP_LLD_CONFIG_H | ||||
| #define _GDISP_LLD_CONFIG_H | ||||
| 
 | ||||
| #if GFX_USE_GDISP | ||||
| 
 | ||||
| /*===========================================================================*/ | ||||
| /* Driver hardware support.                                                  */ | ||||
| /*===========================================================================*/ | ||||
| 
 | ||||
| #define GDISP_HARDWARE_FLUSH			TRUE		// This controller requires flushing
 | ||||
| #define GDISP_HARDWARE_DRAWPIXEL		TRUE | ||||
| #define GDISP_HARDWARE_PIXELREAD		TRUE | ||||
| #define GDISP_HARDWARE_CONTROL			TRUE | ||||
| 
 | ||||
| #define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_GRAY256 | ||||
| 
 | ||||
| #endif	/* GFX_USE_GDISP */ | ||||
| 
 | ||||
| #endif	/* _GDISP_LLD_CONFIG_H */ | ||||
| @ -0,0 +1,2 @@ | ||||
| GFXINC += drivers/gdisp/emulator_lcd | ||||
| GFXSRC += drivers/gdisp/emulator_lcd/emulator_lcd.c | ||||
| @ -0,0 +1,10 @@ | ||||
| #define GDISP_DRIVER_VMT		    	GDISPVMT_EMULATOR_LCD_ERGODOX | ||||
| #define GDISP_HARDWARE_DRAWPIXEL		TRUE | ||||
| #define GDISP_HARDWARE_PIXELREAD		TRUE | ||||
| #define GDISP_HARDWARE_CONTROL			TRUE | ||||
| #define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_MONO | ||||
| #define GDISP_SCREEN_WIDTH		        128 | ||||
| #define GDISP_SCREEN_HEIGHT		        32 | ||||
| #define ROTATE_180_IS_FLIP | ||||
| 
 | ||||
| #include "emulator/emulator_driver_impl.h" | ||||
| @ -0,0 +1,2 @@ | ||||
| GFXINC += drivers/gdisp/emulator_led | ||||
| GFXSRC += drivers/gdisp/emulator_led/emulator_led.c | ||||
| @ -0,0 +1,10 @@ | ||||
| #define GDISP_DRIVER_VMT			    GDISPVMT_EMULATOR_LED_ERGODOX | ||||
| #define GDISP_HARDWARE_DRAWPIXEL		TRUE | ||||
| #define GDISP_HARDWARE_PIXELREAD		TRUE | ||||
| #define GDISP_HARDWARE_CONTROL			TRUE | ||||
| #define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_MONO | ||||
| #define GDISP_SCREEN_WIDTH		        7 | ||||
| #define GDISP_SCREEN_HEIGHT		        7 | ||||
| #define ROTATE_180_IS_FLIP | ||||
| 
 | ||||
| #include "emulator/emulator_driver_impl.h" | ||||
| @ -0,0 +1,127 @@ | ||||
| /*
 | ||||
|  * This file is subject to the terms of the GFX License. If a copy of | ||||
|  * the license was not distributed with this file, you can obtain one at: | ||||
|  * | ||||
|  *              http://ugfx.org/license.html
 | ||||
|  */ | ||||
| 
 | ||||
| #ifndef _GDISP_LLD_BOARD_H | ||||
| #define _GDISP_LLD_BOARD_H | ||||
| 
 | ||||
| #include "print.h" | ||||
| 
 | ||||
| #define ST7565_LCD_BIAS         ST7565_LCD_BIAS_9 // actually 6
 | ||||
| #define ST7565_ADC              ST7565_ADC_NORMAL | ||||
| #define ST7565_COM_SCAN         ST7565_COM_SCAN_DEC | ||||
| #define ST7565_PAGE_ORDER       0,1,2,3 | ||||
| /*
 | ||||
|  * Custom page order for several LCD boards, e.g. HEM12864-99 | ||||
|  * #define ST7565_PAGE_ORDER       4,5,6,7,0,1,2,3 | ||||
|  */ | ||||
| 
 | ||||
| #define ST7565_GPIOPORT GPIOC | ||||
| #define ST7565_PORT PORTC | ||||
| #define ST7565_A0_PIN 7 | ||||
| #define ST7565_RST_PIN 8 | ||||
| #define ST7565_MOSI_PIN 6 | ||||
| #define ST7565_SLCK_PIN 5 | ||||
| #define ST7565_SS_PIN 4 | ||||
| 
 | ||||
| #define palSetPadModeRaw(portname, bits) \ | ||||
|     ST7565_PORT->PCR[ST7565_##portname##_PIN] = bits | ||||
| 
 | ||||
| #define palSetPadModeNamed(portname, portmode) \ | ||||
|     palSetPadMode(ST7565_GPIOPORT, ST7565_##portname##_PIN, portmode) | ||||
| 
 | ||||
| #define ST7565_SPI_MODE PORTx_PCRn_DSE | PORTx_PCRn_MUX(2) | ||||
| // DSPI Clock and Transfer Attributes
 | ||||
| // Frame Size: 8 bits
 | ||||
| // MSB First
 | ||||
| // CLK Low by default
 | ||||
| static const SPIConfig spi1config = { | ||||
| 	NULL, | ||||
| 	/* HW dependent part.*/ | ||||
| 	ST7565_GPIOPORT, | ||||
|     ST7565_SS_PIN, | ||||
|     SPIx_CTARn_FMSZ(7) | ||||
|     | SPIx_CTARn_ASC(7) | ||||
|     | SPIx_CTARn_DT(7) | ||||
|     | SPIx_CTARn_CSSCK(7) | ||||
|     | SPIx_CTARn_PBR(0) | ||||
|     | SPIx_CTARn_BR(7) | ||||
| 	//SPI_CR1_BR_0
 | ||||
| }; | ||||
| 
 | ||||
| static bool_t st7565_is_data_mode = 1; | ||||
| 
 | ||||
| static GFXINLINE void init_board(GDisplay *g) { | ||||
|     (void) g; | ||||
|     palSetPadModeNamed(A0, PAL_MODE_OUTPUT_PUSHPULL); | ||||
|     palSetPad(ST7565_GPIOPORT, ST7565_A0_PIN); | ||||
|     st7565_is_data_mode = 1; | ||||
|     palSetPadModeNamed(RST, PAL_MODE_OUTPUT_PUSHPULL); | ||||
|     palSetPad(ST7565_GPIOPORT, ST7565_RST_PIN); | ||||
|     palSetPadModeRaw(MOSI, ST7565_SPI_MODE); | ||||
|     palSetPadModeRaw(SLCK, ST7565_SPI_MODE); | ||||
|     palSetPadModeRaw(SS, ST7565_SPI_MODE); | ||||
| 
 | ||||
|     spiInit(); | ||||
|     spiStart(&SPID1, &spi1config); | ||||
|     spiSelect(&SPID1); | ||||
| } | ||||
| 
 | ||||
| static GFXINLINE void post_init_board(GDisplay *g) { | ||||
| 	(void) g; | ||||
| } | ||||
| 
 | ||||
| static GFXINLINE void setpin_reset(GDisplay *g, bool_t state) { | ||||
|     (void) g; | ||||
|     if (state) { | ||||
|         palClearPad(ST7565_GPIOPORT, ST7565_RST_PIN); | ||||
|     } | ||||
|     else { | ||||
|         palSetPad(ST7565_GPIOPORT, ST7565_RST_PIN); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static GFXINLINE void acquire_bus(GDisplay *g) { | ||||
|     (void) g; | ||||
|     // Only the LCD is using the SPI bus, so no need to acquire
 | ||||
|     // spiAcquireBus(&SPID1);
 | ||||
| } | ||||
| 
 | ||||
| static GFXINLINE void release_bus(GDisplay *g) { | ||||
|     (void) g; | ||||
|     // Only the LCD is using the SPI bus, so no need to release
 | ||||
|     //spiReleaseBus(&SPID1);
 | ||||
| } | ||||
| 
 | ||||
| static GFXINLINE void write_cmd(GDisplay *g, uint8_t cmd) { | ||||
| 	(void) g; | ||||
| 	if (st7565_is_data_mode) { | ||||
| 	    // The sleeps need to be at lest 10 vs 25 ns respectively
 | ||||
| 	    // So let's sleep two ticks, one tick might not be enough
 | ||||
| 	    // if we are at the end of the tick
 | ||||
| 	    chThdSleep(2); | ||||
|         palClearPad(ST7565_GPIOPORT, ST7565_A0_PIN); | ||||
|         chThdSleep(2); | ||||
|         st7565_is_data_mode = 0; | ||||
| 	} | ||||
| 	spiSend(&SPID1, 1, &cmd); | ||||
| } | ||||
| 
 | ||||
| static GFXINLINE void write_data(GDisplay *g, uint8_t* data, uint16_t length) { | ||||
| 	(void) g; | ||||
| 	if (!st7565_is_data_mode) { | ||||
| 	    // The sleeps need to be at lest 10 vs 25 ns respectively
 | ||||
| 	    // So let's sleep two ticks, one tick might not be enough
 | ||||
| 	    // if we are at the end of the tick
 | ||||
| 	    chThdSleep(2); | ||||
|         palSetPad(ST7565_GPIOPORT, ST7565_A0_PIN); | ||||
| 	    chThdSleep(2); | ||||
|         st7565_is_data_mode = 1; | ||||
| 	} | ||||
| 	spiSend(&SPID1, length, data); | ||||
| } | ||||
| 
 | ||||
| #endif /* _GDISP_LLD_BOARD_H */ | ||||
| @ -0,0 +1,2 @@ | ||||
| GFXINC += drivers/gdisp/st7565ergodox | ||||
| GFXSRC += drivers/gdisp/st7565ergodox/gdisp_lld_ST7565.c | ||||
| @ -0,0 +1,292 @@ | ||||
| /*
 | ||||
|  * This file is subject to the terms of the GFX License. If a copy of | ||||
|  * the license was not distributed with this file, you can obtain one at: | ||||
|  * | ||||
|  *              http://ugfx.org/license.html
 | ||||
|  */ | ||||
| 
 | ||||
| #include "gfx.h" | ||||
| 
 | ||||
| #if GFX_USE_GDISP | ||||
| 
 | ||||
| #define GDISP_DRIVER_VMT			GDISPVMT_ST7565_ERGODOX | ||||
| #include "drivers/gdisp/st7565ergodox/gdisp_lld_config.h" | ||||
| #include "src/gdisp/gdisp_driver.h" | ||||
| 
 | ||||
| #include "board_ST7565.h" | ||||
| 
 | ||||
| /*===========================================================================*/ | ||||
| /* Driver local definitions.                                                 */ | ||||
| /*===========================================================================*/ | ||||
| 
 | ||||
| #ifndef GDISP_SCREEN_HEIGHT | ||||
| 	#define GDISP_SCREEN_HEIGHT		32 | ||||
| #endif | ||||
| #ifndef GDISP_SCREEN_WIDTH | ||||
| 	#define GDISP_SCREEN_WIDTH		128 | ||||
| #endif | ||||
| #ifndef GDISP_INITIAL_CONTRAST | ||||
| 	#define GDISP_INITIAL_CONTRAST	0 | ||||
| #endif | ||||
| #ifndef GDISP_INITIAL_BACKLIGHT | ||||
| 	#define GDISP_INITIAL_BACKLIGHT	100 | ||||
| #endif | ||||
| 
 | ||||
| #define GDISP_FLG_NEEDFLUSH			(GDISP_FLG_DRIVER<<0) | ||||
| 
 | ||||
| #include "drivers/gdisp/st7565ergodox/st7565.h" | ||||
| 
 | ||||
| /*===========================================================================*/ | ||||
| /* Driver config defaults for backward compatibility.               	     */ | ||||
| /*===========================================================================*/ | ||||
| #ifndef ST7565_LCD_BIAS | ||||
|   #define ST7565_LCD_BIAS         ST7565_LCD_BIAS_7 | ||||
| #endif | ||||
| #ifndef ST7565_ADC | ||||
|   #define ST7565_ADC              ST7565_ADC_NORMAL | ||||
| #endif | ||||
| #ifndef ST7565_COM_SCAN | ||||
|   #define ST7565_COM_SCAN         ST7565_COM_SCAN_INC | ||||
| #endif | ||||
| #ifndef ST7565_PAGE_ORDER | ||||
|   #define ST7565_PAGE_ORDER       0,1,2,3 | ||||
| #endif | ||||
| 
 | ||||
| /*===========================================================================*/ | ||||
| /* Driver local functions.                                                   */ | ||||
| /*===========================================================================*/ | ||||
| 
 | ||||
| typedef struct{ | ||||
|     bool_t buffer2; | ||||
|     uint8_t ram[GDISP_SCREEN_HEIGHT * GDISP_SCREEN_WIDTH / 8]; | ||||
| }PrivData; | ||||
| 
 | ||||
| // Some common routines and macros
 | ||||
| #define PRIV(g)                         ((PrivData*)g->priv) | ||||
| #define RAM(g)							(PRIV(g)->ram) | ||||
| #define write_cmd2(g, cmd1, cmd2)		{ write_cmd(g, cmd1); write_cmd(g, cmd2); } | ||||
| #define write_cmd3(g, cmd1, cmd2, cmd3)	{ write_cmd(g, cmd1); write_cmd(g, cmd2); write_cmd(g, cmd3); } | ||||
| 
 | ||||
| // Some common routines and macros
 | ||||
| #define delay(us)			gfxSleepMicroseconds(us) | ||||
| #define delay_ms(ms)		gfxSleepMilliseconds(ms) | ||||
| 
 | ||||
| #define xyaddr(x, y)		((x) + ((y)>>3)*GDISP_SCREEN_WIDTH) | ||||
| #define xybit(y)			(1<<((y)&7)) | ||||
| 
 | ||||
| /*===========================================================================*/ | ||||
| /* Driver exported functions.                                                */ | ||||
| /*===========================================================================*/ | ||||
| 
 | ||||
| /*
 | ||||
|  * As this controller can't update on a pixel boundary we need to maintain the | ||||
|  * the entire display surface in memory so that we can do the necessary bit | ||||
|  * operations. Fortunately it is a small display in monochrome. | ||||
|  * 64 * 128 / 8 = 1024 bytes. | ||||
|  */ | ||||
| 
 | ||||
| LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { | ||||
| 	// The private area is the display surface.
 | ||||
| 	g->priv = gfxAlloc(sizeof(PrivData)); | ||||
| 	PRIV(g)->buffer2 = false; | ||||
| 
 | ||||
| 	// Initialise the board interface
 | ||||
| 	init_board(g); | ||||
| 
 | ||||
| 	// Hardware reset
 | ||||
| 	setpin_reset(g, TRUE); | ||||
| 	gfxSleepMilliseconds(20); | ||||
| 	setpin_reset(g, FALSE); | ||||
| 	gfxSleepMilliseconds(20); | ||||
| 
 | ||||
| 	acquire_bus(g); | ||||
|     write_cmd(g, ST7565_DISPLAY_OFF); | ||||
| 	write_cmd(g, ST7565_LCD_BIAS); | ||||
|     write_cmd(g, ST7565_ADC); | ||||
|     write_cmd(g, ST7565_COM_SCAN); | ||||
|      | ||||
|     write_cmd(g, ST7565_START_LINE | 0); | ||||
| 
 | ||||
| 	write_cmd(g, ST7565_RESISTOR_RATIO | 0x6); | ||||
| 
 | ||||
| 	// turn on voltage converter (VC=1, VR=0, VF=0)
 | ||||
| 	write_cmd(g, ST7565_POWER_CONTROL | 0x04); | ||||
| 	delay_ms(50); | ||||
| 
 | ||||
| 	// turn on voltage regulator (VC=1, VR=1, VF=0)
 | ||||
| 	write_cmd(g, ST7565_POWER_CONTROL | 0x06); | ||||
| 	delay_ms(50); | ||||
| 
 | ||||
| 	// turn on voltage follower (VC=1, VR=1, VF=1)
 | ||||
| 	write_cmd(g, ST7565_POWER_CONTROL | 0x07); | ||||
| 	delay_ms(50); | ||||
| 
 | ||||
| 	write_cmd(g, 0xE2); | ||||
|     write_cmd(g, ST7565_COM_SCAN); | ||||
| 	write_cmd2(g, ST7565_CONTRAST, GDISP_INITIAL_CONTRAST*64/101); | ||||
| 	//write_cmd2(g, ST7565_CONTRAST, 0);
 | ||||
| 	write_cmd(g, ST7565_DISPLAY_ON); | ||||
| 	write_cmd(g, ST7565_ALLON_NORMAL); | ||||
| 	write_cmd(g, ST7565_INVERT_DISPLAY); | ||||
| 
 | ||||
| 	write_cmd(g, ST7565_RMW); | ||||
| 
 | ||||
|     // Finish Init
 | ||||
|     post_init_board(g); | ||||
| 
 | ||||
|  	// Release the bus
 | ||||
| 	release_bus(g); | ||||
| 
 | ||||
| 	/* Initialise the GDISP structure */ | ||||
| 	g->g.Width = GDISP_SCREEN_WIDTH; | ||||
| 	g->g.Height = GDISP_SCREEN_HEIGHT; | ||||
| 	g->g.Orientation = GDISP_ROTATE_0; | ||||
| 	g->g.Powermode = powerOn; | ||||
| 	g->g.Backlight = GDISP_INITIAL_BACKLIGHT; | ||||
| 	g->g.Contrast = GDISP_INITIAL_CONTRAST; | ||||
| 	return TRUE; | ||||
| } | ||||
| 
 | ||||
| #if GDISP_HARDWARE_FLUSH | ||||
| 	LLDSPEC void gdisp_lld_flush(GDisplay *g) { | ||||
| 		unsigned	p; | ||||
| 
 | ||||
| 		// Don't flush if we don't need it.
 | ||||
| 		if (!(g->flags & GDISP_FLG_NEEDFLUSH)) | ||||
| 			return; | ||||
| 
 | ||||
| 		acquire_bus(g); | ||||
| 		unsigned dstOffset = (PRIV(g)->buffer2 ? 4 : 0); | ||||
| 		for (p = 0; p < 4; p++) { | ||||
| 			write_cmd(g, ST7565_PAGE | (p + dstOffset)); | ||||
| 			write_cmd(g, ST7565_COLUMN_MSB | 0); | ||||
| 			write_cmd(g, ST7565_COLUMN_LSB | 0); | ||||
| 			write_cmd(g, ST7565_RMW); | ||||
| 			write_data(g, RAM(g) + (p*GDISP_SCREEN_WIDTH), GDISP_SCREEN_WIDTH); | ||||
| 		} | ||||
| 		unsigned line = (PRIV(g)->buffer2 ? 32 : 0); | ||||
|         write_cmd(g, ST7565_START_LINE | line); | ||||
|         PRIV(g)->buffer2 = !PRIV(g)->buffer2; | ||||
| 		release_bus(g); | ||||
| 
 | ||||
| 		g->flags &= ~GDISP_FLG_NEEDFLUSH; | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| #if GDISP_HARDWARE_DRAWPIXEL | ||||
| 	LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) { | ||||
| 		coord_t		x, y; | ||||
| 
 | ||||
| 		switch(g->g.Orientation) { | ||||
| 		default: | ||||
| 		case GDISP_ROTATE_0: | ||||
| 			x = g->p.x; | ||||
| 			y = g->p.y; | ||||
| 			break; | ||||
| 		case GDISP_ROTATE_90: | ||||
| 			x = g->p.y; | ||||
| 			y = GDISP_SCREEN_HEIGHT-1 - g->p.x; | ||||
| 			break; | ||||
| 		case GDISP_ROTATE_180: | ||||
| 			x = GDISP_SCREEN_WIDTH-1 - g->p.x; | ||||
| 			y = GDISP_SCREEN_HEIGHT-1 - g->p.y; | ||||
| 			break; | ||||
| 		case GDISP_ROTATE_270: | ||||
| 			x = GDISP_SCREEN_HEIGHT-1 - g->p.y; | ||||
| 			y = g->p.x; | ||||
| 			break; | ||||
| 		} | ||||
| 		if (gdispColor2Native(g->p.color) != Black) | ||||
| 			RAM(g)[xyaddr(x, y)] |= xybit(y); | ||||
| 		else | ||||
| 			RAM(g)[xyaddr(x, y)] &= ~xybit(y); | ||||
| 		g->flags |= GDISP_FLG_NEEDFLUSH; | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| #if GDISP_HARDWARE_PIXELREAD | ||||
| 	LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) { | ||||
| 		coord_t		x, y; | ||||
| 
 | ||||
| 		switch(g->g.Orientation) { | ||||
| 		default: | ||||
| 		case GDISP_ROTATE_0: | ||||
| 			x = g->p.x; | ||||
| 			y = g->p.y; | ||||
| 			break; | ||||
| 		case GDISP_ROTATE_90: | ||||
| 			x = g->p.y; | ||||
| 			y = GDISP_SCREEN_HEIGHT-1 - g->p.x; | ||||
| 			break; | ||||
| 		case GDISP_ROTATE_180: | ||||
| 			x = GDISP_SCREEN_WIDTH-1 - g->p.x; | ||||
| 			y = GDISP_SCREEN_HEIGHT-1 - g->p.y; | ||||
| 			break; | ||||
| 		case GDISP_ROTATE_270: | ||||
| 			x = GDISP_SCREEN_HEIGHT-1 - g->p.y; | ||||
| 			y = g->p.x; | ||||
| 			break; | ||||
| 		} | ||||
| 		return (RAM(g)[xyaddr(x, y)] & xybit(y)) ? White : Black; | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| #if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL | ||||
| 	LLDSPEC void gdisp_lld_control(GDisplay *g) { | ||||
| 		switch(g->p.x) { | ||||
| 		case GDISP_CONTROL_POWER: | ||||
| 			if (g->g.Powermode == (powermode_t)g->p.ptr) | ||||
| 				return; | ||||
| 			switch((powermode_t)g->p.ptr) { | ||||
| 			case powerOff: | ||||
| 			case powerSleep: | ||||
| 			case powerDeepSleep: | ||||
| 				acquire_bus(g); | ||||
| 				write_cmd(g, ST7565_DISPLAY_OFF); | ||||
| 				release_bus(g); | ||||
| 				break; | ||||
| 			case powerOn: | ||||
| 				acquire_bus(g); | ||||
| 				write_cmd(g, ST7565_DISPLAY_ON); | ||||
| 				release_bus(g); | ||||
| 				break; | ||||
| 			default: | ||||
| 				return; | ||||
| 			} | ||||
| 			g->g.Powermode = (powermode_t)g->p.ptr; | ||||
| 			return; | ||||
| 
 | ||||
| 		case GDISP_CONTROL_ORIENTATION: | ||||
| 			if (g->g.Orientation == (orientation_t)g->p.ptr) | ||||
| 				return; | ||||
| 			switch((orientation_t)g->p.ptr) { | ||||
| 			/* Rotation is handled by the drawing routines */ | ||||
| 			case GDISP_ROTATE_0: | ||||
| 			case GDISP_ROTATE_180: | ||||
| 				g->g.Height = GDISP_SCREEN_HEIGHT; | ||||
| 				g->g.Width = GDISP_SCREEN_WIDTH; | ||||
| 				break; | ||||
| 			case GDISP_ROTATE_90: | ||||
| 			case GDISP_ROTATE_270: | ||||
| 				g->g.Height = GDISP_SCREEN_WIDTH; | ||||
| 				g->g.Width = GDISP_SCREEN_HEIGHT; | ||||
| 				break; | ||||
| 			default: | ||||
| 				return; | ||||
| 			} | ||||
| 			g->g.Orientation = (orientation_t)g->p.ptr; | ||||
| 			return; | ||||
| 
 | ||||
| 		case GDISP_CONTROL_CONTRAST: | ||||
|             if ((unsigned)g->p.ptr > 100) | ||||
|             	g->p.ptr = (void *)100; | ||||
| 			acquire_bus(g); | ||||
| 			write_cmd2(g, ST7565_CONTRAST, ((((unsigned)g->p.ptr)<<6)/101) & 0x3F); | ||||
| 			release_bus(g); | ||||
|             g->g.Contrast = (unsigned)g->p.ptr; | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| #endif // GDISP_NEED_CONTROL
 | ||||
| 
 | ||||
| #endif // GFX_USE_GDISP
 | ||||
| @ -0,0 +1,26 @@ | ||||
| /*
 | ||||
|  * This file is subject to the terms of the GFX License. If a copy of | ||||
|  * the license was not distributed with this file, you can obtain one at: | ||||
|  * | ||||
|  *              http://ugfx.org/license.html
 | ||||
|  */ | ||||
| 
 | ||||
| #ifndef _GDISP_LLD_CONFIG_H | ||||
| #define _GDISP_LLD_CONFIG_H | ||||
| 
 | ||||
| #if GFX_USE_GDISP | ||||
| 
 | ||||
| /*===========================================================================*/ | ||||
| /* Driver hardware support.                                                  */ | ||||
| /*===========================================================================*/ | ||||
| 
 | ||||
| #define GDISP_HARDWARE_FLUSH			TRUE		// This controller requires flushing
 | ||||
| #define GDISP_HARDWARE_DRAWPIXEL		TRUE | ||||
| #define GDISP_HARDWARE_PIXELREAD		TRUE | ||||
| #define GDISP_HARDWARE_CONTROL			TRUE | ||||
| 
 | ||||
| #define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_MONO | ||||
| 
 | ||||
| #endif	/* GFX_USE_GDISP */ | ||||
| 
 | ||||
| #endif	/* _GDISP_LLD_CONFIG_H */ | ||||
| @ -0,0 +1,37 @@ | ||||
| /*
 | ||||
|  * This file is subject to the terms of the GFX License. If a copy of | ||||
|  * the license was not distributed with this file, you can obtain one at: | ||||
|  * | ||||
|  *              http://ugfx.org/license.html
 | ||||
|  */ | ||||
| 
 | ||||
| #ifndef _ST7565_H | ||||
| #define _ST7565_H | ||||
| 
 | ||||
| #define ST7565_CONTRAST             0x81 | ||||
| #define ST7565_ALLON_NORMAL         0xA4 | ||||
| #define ST7565_ALLON                0xA5 | ||||
| #define ST7565_POSITIVE_DISPLAY     0xA6 | ||||
| #define ST7565_INVERT_DISPLAY       0xA7 | ||||
| #define ST7565_DISPLAY_OFF          0xAE | ||||
| #define ST7565_DISPLAY_ON           0xAF | ||||
| 
 | ||||
| #define ST7565_LCD_BIAS_7           0xA3 | ||||
| #define ST7565_LCD_BIAS_9           0xA2 | ||||
| 
 | ||||
| #define ST7565_ADC_NORMAL           0xA0 | ||||
| #define ST7565_ADC_REVERSE          0xA1 | ||||
| 
 | ||||
| #define ST7565_COM_SCAN_INC         0xC0 | ||||
| #define ST7565_COM_SCAN_DEC         0xC8 | ||||
| 
 | ||||
| #define ST7565_START_LINE           0x40 | ||||
| #define ST7565_PAGE                 0xB0 | ||||
| #define ST7565_COLUMN_MSB           0x10 | ||||
| #define ST7565_COLUMN_LSB           0x00 | ||||
| #define ST7565_RMW                  0xE0 | ||||
| 
 | ||||
| #define ST7565_RESISTOR_RATIO       0x20 | ||||
| #define ST7565_POWER_CONTROL        0x28 | ||||
| 
 | ||||
| #endif /* _ST7565_H */ | ||||
| @ -0,0 +1,331 @@ | ||||
| /**
 | ||||
|  * This file has a different license to the rest of the uGFX system. | ||||
|  * You can copy, modify and distribute this file as you see fit. | ||||
|  * You do not need to publish your source modifications to this file. | ||||
|  * The only thing you are not permitted to do is to relicense it | ||||
|  * under a different license. | ||||
|  */ | ||||
| 
 | ||||
| /**
 | ||||
|  * Copy this file into your project directory and rename it as gfxconf.h | ||||
|  * Edit your copy to turn on the uGFX features you want to use. | ||||
|  * The values below are the defaults. | ||||
|  * | ||||
|  * Only remove the comments from lines where you want to change the | ||||
|  * default value. This allows definitions to be included from | ||||
|  * driver makefiles when required and provides the best future | ||||
|  * compatibility for your project. | ||||
|  * | ||||
|  * Please use spaces instead of tabs in this file. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef _GFXCONF_H | ||||
| #define _GFXCONF_H | ||||
| 
 | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| // GOS - One of these must be defined, preferably in your Makefile       //
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| //#define GFX_USE_OS_CHIBIOS                           TRUE
 | ||||
| //#define GFX_USE_OS_FREERTOS                          FALSE
 | ||||
| //    #define GFX_FREERTOS_USE_TRACE                   FALSE
 | ||||
| //#define GFX_USE_OS_WIN32                             FALSE
 | ||||
| //#define GFX_USE_OS_LINUX                             FALSE
 | ||||
| //#define GFX_USE_OS_OSX                               FALSE
 | ||||
| //#define GFX_USE_OS_ECOS                              FALSE
 | ||||
| //#define GFX_USE_OS_RAWRTOS                           FALSE
 | ||||
| //#define GFX_USE_OS_ARDUINO                           FALSE
 | ||||
| //#define GFX_USE_OS_KEIL                              FALSE
 | ||||
| //#define GFX_USE_OS_CMSIS                             FALSE
 | ||||
| //#define GFX_USE_OS_RAW32                             FALSE
 | ||||
| //    #define INTERRUPTS_OFF()                         optional_code
 | ||||
| //    #define INTERRUPTS_ON()                          optional_code
 | ||||
| // These are not defined by default for some reason
 | ||||
| #define GOS_NEED_X_THREADS	FALSE | ||||
| #define GOS_NEED_X_HEAP		FALSE | ||||
| 
 | ||||
| // Options that (should where relevant) apply to all operating systems
 | ||||
|     #define GFX_NO_INLINE                            FALSE | ||||
| //    #define GFX_COMPILER                             GFX_COMPILER_UNKNOWN
 | ||||
| //    #define GFX_CPU                                  GFX_CPU_UNKNOWN
 | ||||
| //    #define GFX_OS_HEAP_SIZE                         0
 | ||||
| //    #define GFX_OS_NO_INIT                           FALSE
 | ||||
| //    #define GFX_OS_INIT_NO_WARNING                   FALSE
 | ||||
| //    #define GFX_OS_PRE_INIT_FUNCTION                 myHardwareInitRoutine
 | ||||
| //    #define GFX_OS_EXTRA_INIT_FUNCTION               myOSInitRoutine
 | ||||
| //    #define GFX_OS_EXTRA_DEINIT_FUNCTION             myOSDeInitRoutine
 | ||||
| 
 | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| // GDISP                                                                 //
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| #define GFX_USE_GDISP                                TRUE | ||||
| 
 | ||||
| //#define GDISP_NEED_AUTOFLUSH                         FALSE
 | ||||
| //#define GDISP_NEED_TIMERFLUSH                        FALSE
 | ||||
| //#define GDISP_NEED_VALIDATION                        TRUE
 | ||||
| //#define GDISP_NEED_CLIP                              TRUE
 | ||||
| #define GDISP_NEED_CIRCLE                            TRUE | ||||
| #define GDISP_NEED_ELLIPSE                           TRUE | ||||
| #define GDISP_NEED_ARC                               TRUE | ||||
| #define GDISP_NEED_ARCSECTORS                        TRUE | ||||
| #define GDISP_NEED_CONVEX_POLYGON                    TRUE | ||||
| //#define GDISP_NEED_SCROLL                            FALSE
 | ||||
| #define GDISP_NEED_PIXELREAD                         TRUE | ||||
| #define GDISP_NEED_CONTROL                           TRUE | ||||
| //#define GDISP_NEED_QUERY                             FALSE
 | ||||
| //#define GDISP_NEED_MULTITHREAD                       FALSE
 | ||||
| //#define GDISP_NEED_STREAMING                         FALSE
 | ||||
| #define GDISP_NEED_TEXT                              TRUE | ||||
| //    #define GDISP_NEED_TEXT_WORDWRAP                 FALSE
 | ||||
| //    #define GDISP_NEED_ANTIALIAS                     FALSE
 | ||||
| //    #define GDISP_NEED_UTF8                          FALSE
 | ||||
|     #define GDISP_NEED_TEXT_KERNING                  TRUE | ||||
| //    #define GDISP_INCLUDE_FONT_UI1                   FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_UI2                   FALSE		// The smallest preferred font.
 | ||||
| //    #define GDISP_INCLUDE_FONT_LARGENUMBERS          FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_DEJAVUSANS10          FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_DEJAVUSANS12          FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_DEJAVUSANS16          FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_DEJAVUSANS20          FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_DEJAVUSANS24          FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_DEJAVUSANS32          FALSE
 | ||||
|     #define GDISP_INCLUDE_FONT_DEJAVUSANSBOLD12      TRUE | ||||
| //    #define GDISP_INCLUDE_FONT_FIXED_10X20           FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_FIXED_7X14            FALSE
 | ||||
|     #define GDISP_INCLUDE_FONT_FIXED_5X8             TRUE | ||||
| //    #define GDISP_INCLUDE_FONT_DEJAVUSANS12_AA       FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_DEJAVUSANS16_AA       FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_DEJAVUSANS20_AA       FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_DEJAVUSANS24_AA       FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_DEJAVUSANS32_AA       FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_DEJAVUSANSBOLD12_AA   FALSE
 | ||||
| //    #define GDISP_INCLUDE_USER_FONTS                 FALSE
 | ||||
| 
 | ||||
| //#define GDISP_NEED_IMAGE                             FALSE
 | ||||
| //    #define GDISP_NEED_IMAGE_NATIVE                  FALSE
 | ||||
| //    #define GDISP_NEED_IMAGE_GIF                     FALSE
 | ||||
| //    #define GDISP_NEED_IMAGE_BMP                     FALSE
 | ||||
| //        #define GDISP_NEED_IMAGE_BMP_1               FALSE
 | ||||
| //        #define GDISP_NEED_IMAGE_BMP_4               FALSE
 | ||||
| //        #define GDISP_NEED_IMAGE_BMP_4_RLE           FALSE
 | ||||
| //        #define GDISP_NEED_IMAGE_BMP_8               FALSE
 | ||||
| //        #define GDISP_NEED_IMAGE_BMP_8_RLE           FALSE
 | ||||
| //        #define GDISP_NEED_IMAGE_BMP_16              FALSE
 | ||||
| //        #define GDISP_NEED_IMAGE_BMP_24              FALSE
 | ||||
| //        #define GDISP_NEED_IMAGE_BMP_32              FALSE
 | ||||
| //    #define GDISP_NEED_IMAGE_JPG                     FALSE
 | ||||
| //    #define GDISP_NEED_IMAGE_PNG                     FALSE
 | ||||
| //    #define GDISP_NEED_IMAGE_ACCOUNTING              FALSE
 | ||||
| #ifdef EMULATOR | ||||
| #define GDISP_NEED_PIXMAP                            TRUE | ||||
| #endif | ||||
| //    #define GDISP_NEED_PIXMAP_IMAGE                  FALSE
 | ||||
| 
 | ||||
| //#define GDISP_DEFAULT_ORIENTATION                    GDISP_ROTATE_LANDSCAPE    // If not defined the native hardware orientation is used.
 | ||||
| //#define GDISP_LINEBUF_SIZE                           128
 | ||||
| //#define GDISP_STARTUP_COLOR                          Black
 | ||||
| #define GDISP_NEED_STARTUP_LOGO                      FALSE | ||||
| 
 | ||||
| //#define GDISP_TOTAL_DISPLAYS		                 2
 | ||||
| 
 | ||||
| #ifndef EMULATOR | ||||
| #define GDISP_DRIVER_LIST                            GDISPVMT_ST7565_ERGODOX, GDISPVMT_IS31FL3731C_ERGODOX | ||||
| #else | ||||
| #define GDISP_DRIVER_LIST                            GDISPVMT_EMULATOR_LCD_ERGODOX, GDISPVMT_EMULATOR_LED_ERGODOX | ||||
| #endif | ||||
| 
 | ||||
|     #ifdef GDISP_DRIVER_LIST | ||||
|         // For code and speed optimization define as TRUE or FALSE if all controllers have the same capability
 | ||||
|         #define GDISP_HARDWARE_STREAM_WRITE          FALSE | ||||
|         #define GDISP_HARDWARE_STREAM_READ           FALSE | ||||
|         #define GDISP_HARDWARE_STREAM_POS            FALSE | ||||
|         #define GDISP_HARDWARE_DRAWPIXEL             TRUE | ||||
|         #define GDISP_HARDWARE_CLEARS                FALSE | ||||
|         #define GDISP_HARDWARE_FILLS                 FALSE | ||||
|         #define GDISP_HARDWARE_BITFILLS              FALSE | ||||
|         #define GDISP_HARDWARE_SCROLL                FALSE | ||||
|         #define GDISP_HARDWARE_PIXELREAD             TRUE | ||||
|         #define GDISP_HARDWARE_CONTROL               TRUE | ||||
|         #define GDISP_HARDWARE_QUERY                 FALSE | ||||
|         #define GDISP_HARDWARE_CLIP                  FALSE | ||||
| 
 | ||||
|         #define GDISP_PIXELFORMAT                    GDISP_PIXELFORMAT_RGB888 | ||||
|     #endif | ||||
| 
 | ||||
| // The custom format is not defined for some reason, so define it as error
 | ||||
| // so we don't get compiler warnings
 | ||||
| #define GDISP_PIXELFORMAT_CUSTOM GDISP_PIXELFORMAT_ERROR | ||||
| 
 | ||||
| #define GDISP_USE_GFXNET                             FALSE | ||||
| //    #define GDISP_GFXNET_PORT                        13001
 | ||||
| //    #define GDISP_GFXNET_CUSTOM_LWIP_STARTUP         FALSE
 | ||||
| //    #define GDISP_DONT_WAIT_FOR_NET_DISPLAY          FALSE
 | ||||
| //    #define GDISP_GFXNET_UNSAFE_SOCKETS              FALSE
 | ||||
| 
 | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| // GWIN                                                                  //
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| #define GFX_USE_GWIN                                 FALSE | ||||
| 
 | ||||
| //#define GWIN_NEED_WINDOWMANAGER                      FALSE
 | ||||
| //    #define GWIN_REDRAW_IMMEDIATE                    FALSE
 | ||||
| //    #define GWIN_REDRAW_SINGLEOP                     FALSE
 | ||||
| //    #define GWIN_NEED_FLASHING                       FALSE
 | ||||
| //        #define GWIN_FLASHING_PERIOD                 250
 | ||||
| 
 | ||||
| //#define GWIN_NEED_CONSOLE                            FALSE
 | ||||
| //    #define GWIN_CONSOLE_USE_HISTORY                 FALSE
 | ||||
| //        #define GWIN_CONSOLE_HISTORY_AVERAGING       FALSE
 | ||||
| //        #define GWIN_CONSOLE_HISTORY_ATCREATE        FALSE
 | ||||
| //    #define GWIN_CONSOLE_ESCSEQ                      FALSE
 | ||||
| //    #define GWIN_CONSOLE_USE_BASESTREAM              FALSE
 | ||||
| //    #define GWIN_CONSOLE_USE_FLOAT                   FALSE
 | ||||
| //#define GWIN_NEED_GRAPH                              FALSE
 | ||||
| //#define GWIN_NEED_GL3D                               FALSE
 | ||||
| 
 | ||||
| //#define GWIN_NEED_WIDGET                             FALSE
 | ||||
| //#define GWIN_FOCUS_HIGHLIGHT_WIDTH                   1
 | ||||
| //    #define GWIN_NEED_LABEL                          FALSE
 | ||||
| //        #define GWIN_LABEL_ATTRIBUTE                 FALSE
 | ||||
| //    #define GWIN_NEED_BUTTON                         FALSE
 | ||||
| //        #define GWIN_BUTTON_LAZY_RELEASE             FALSE
 | ||||
| //    #define GWIN_NEED_SLIDER                         FALSE
 | ||||
| //        #define GWIN_SLIDER_NOSNAP                   FALSE
 | ||||
| //        #define GWIN_SLIDER_DEAD_BAND                5
 | ||||
| //        #define GWIN_SLIDER_TOGGLE_INC               20
 | ||||
| //    #define GWIN_NEED_CHECKBOX                       FALSE
 | ||||
| //    #define GWIN_NEED_IMAGE                          FALSE
 | ||||
| //        #define GWIN_NEED_IMAGE_ANIMATION            FALSE
 | ||||
| //    #define GWIN_NEED_RADIO                          FALSE
 | ||||
| //    #define GWIN_NEED_LIST                           FALSE
 | ||||
| //        #define GWIN_NEED_LIST_IMAGES                FALSE
 | ||||
| //    #define GWIN_NEED_PROGRESSBAR                    FALSE
 | ||||
| //        #define GWIN_PROGRESSBAR_AUTO                FALSE
 | ||||
| //    #define GWIN_NEED_KEYBOARD                       FALSE
 | ||||
| //        #define GWIN_KEYBOARD_DEFAULT_LAYOUT         VirtualKeyboard_English1
 | ||||
| //        #define GWIN_NEED_KEYBOARD_ENGLISH1          TRUE
 | ||||
| //    #define GWIN_NEED_TEXTEDIT                       FALSE
 | ||||
| //    #define GWIN_FLAT_STYLING                        FALSE
 | ||||
| //    #define GWIN_WIDGET_TAGS                         FALSE
 | ||||
| 
 | ||||
| //#define GWIN_NEED_CONTAINERS                         FALSE
 | ||||
| //    #define GWIN_NEED_CONTAINER                      FALSE
 | ||||
| //    #define GWIN_NEED_FRAME                          FALSE
 | ||||
| //    #define GWIN_NEED_TABSET                         FALSE
 | ||||
| //        #define GWIN_TABSET_TABHEIGHT                18
 | ||||
| 
 | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| // GEVENT                                                                //
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| #define GFX_USE_GEVENT                               TRUE | ||||
| 
 | ||||
| //#define GEVENT_ASSERT_NO_RESOURCE                    FALSE
 | ||||
| //#define GEVENT_MAXIMUM_SIZE                          32
 | ||||
| //#define GEVENT_MAX_SOURCE_LISTENERS                  32
 | ||||
| 
 | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| // GTIMER                                                                //
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| #define GFX_USE_GTIMER                               FALSE | ||||
| 
 | ||||
| //#define GTIMER_THREAD_PRIORITY                       HIGH_PRIORITY
 | ||||
| //#define GTIMER_THREAD_WORKAREA_SIZE                  2048
 | ||||
| 
 | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| // GQUEUE                                                                //
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| #define GFX_USE_GQUEUE                               FALSE | ||||
| 
 | ||||
| //#define GQUEUE_NEED_ASYNC                            FALSE
 | ||||
| //#define GQUEUE_NEED_GSYNC                            FALSE
 | ||||
| //#define GQUEUE_NEED_FSYNC                            FALSE
 | ||||
| //#define GQUEUE_NEED_BUFFERS                          FALSE
 | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| // GINPUT                                                                //
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| #define GFX_USE_GINPUT                               FALSE | ||||
| 
 | ||||
| //#define GINPUT_NEED_MOUSE                            FALSE
 | ||||
| //    #define GINPUT_TOUCH_STARTRAW                    FALSE
 | ||||
| //    #define GINPUT_TOUCH_NOTOUCH                     FALSE
 | ||||
| //    #define GINPUT_TOUCH_NOCALIBRATE                 FALSE
 | ||||
| //    #define GINPUT_TOUCH_NOCALIBRATE_GUI             FALSE
 | ||||
| //    #define GINPUT_MOUSE_POLL_PERIOD                 25
 | ||||
| //    #define GINPUT_MOUSE_CLICK_TIME                  300
 | ||||
| //    #define GINPUT_TOUCH_CXTCLICK_TIME               700
 | ||||
| //    #define GINPUT_TOUCH_USER_CALIBRATION_LOAD       FALSE
 | ||||
| //    #define GINPUT_TOUCH_USER_CALIBRATION_SAVE       FALSE
 | ||||
| //    #define GMOUSE_DRIVER_LIST                       GMOUSEVMT_Win32, GMOUSEVMT_Win32
 | ||||
| //#define GINPUT_NEED_KEYBOARD                         FALSE
 | ||||
| //    #define GINPUT_KEYBOARD_POLL_PERIOD              200
 | ||||
| //    #define GKEYBOARD_DRIVER_LIST                    GKEYBOARDVMT_Win32, GKEYBOARDVMT_Win32
 | ||||
| //    #define GKEYBOARD_LAYOUT_OFF                     FALSE
 | ||||
| //        #define GKEYBOARD_LAYOUT_SCANCODE2_US        FALSE
 | ||||
| //#define GINPUT_NEED_TOGGLE                           FALSE
 | ||||
| //#define GINPUT_NEED_DIAL                             FALSE
 | ||||
| 
 | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| // GFILE                                                                 //
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| #define GFX_USE_GFILE                                FALSE | ||||
| 
 | ||||
| //#define GFILE_NEED_PRINTG                            FALSE
 | ||||
| //#define GFILE_NEED_SCANG                             FALSE
 | ||||
| //#define GFILE_NEED_STRINGS                           FALSE
 | ||||
| //#define GFILE_NEED_FILELISTS                         FALSE
 | ||||
| //#define GFILE_NEED_STDIO                             FALSE
 | ||||
| //#define GFILE_NEED_NOAUTOMOUNT                       FALSE
 | ||||
| //#define GFILE_NEED_NOAUTOSYNC                        FALSE
 | ||||
| 
 | ||||
| //#define GFILE_NEED_MEMFS                             FALSE
 | ||||
| //#define GFILE_NEED_ROMFS                             FALSE
 | ||||
| //#define GFILE_NEED_RAMFS                             FALSE
 | ||||
| //#define GFILE_NEED_FATFS                             FALSE
 | ||||
| //#define GFILE_NEED_NATIVEFS                          FALSE
 | ||||
| //#define GFILE_NEED_CHBIOSFS                          FALSE
 | ||||
| 
 | ||||
| //#define GFILE_ALLOW_FLOATS                           FALSE
 | ||||
| //#define GFILE_ALLOW_DEVICESPECIFIC                   FALSE
 | ||||
| //#define GFILE_MAX_GFILES                             3
 | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| // GADC                                                                  //
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| #define GFX_USE_GADC                                 FALSE | ||||
| 
 | ||||
| //#define GADC_MAX_LOWSPEED_DEVICES                    4
 | ||||
| 
 | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| // GAUDIO                                                                //
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| #define GFX_USE_GAUDIO                               FALSE | ||||
| // There seems to be a bug in the ugfx code, the wrong define is used
 | ||||
| // So define it in order to avoid warnings
 | ||||
| #define GFX_USE_GAUDIN                               GFX_USE_GAUDIO | ||||
| //    #define GAUDIO_NEED_PLAY                         FALSE
 | ||||
| //    #define GAUDIO_NEED_RECORD                       FALSE
 | ||||
| 
 | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| // GMISC                                                                 //
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| #define GFX_USE_GMISC                                TRUE | ||||
| 
 | ||||
| //#define GMISC_NEED_ARRAYOPS                          FALSE
 | ||||
| //#define GMISC_NEED_FASTTRIG                          FALSE
 | ||||
| //#define GMISC_NEED_FIXEDTRIG                         FALSE
 | ||||
| //#define GMISC_NEED_INVSQRT                           FALSE
 | ||||
| //    #define GMISC_INVSQRT_MIXED_ENDIAN               FALSE
 | ||||
| //    #define GMISC_INVSQRT_REAL_SLOW                  FALSE
 | ||||
| #define GMISC_NEED_MATRIXFLOAT2D                     TRUE | ||||
| #define GMISC_NEED_MATRIXFIXED2D                     FALSE | ||||
| 
 | ||||
| #endif /* _GFXCONF_H */ | ||||
| @ -0,0 +1,168 @@ | ||||
| /*
 | ||||
| Copyright 2016 Fred Sundvik <fsundvik@gmail.com> | ||||
| 
 | ||||
| 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/>.
 | ||||
| */ | ||||
| 
 | ||||
| // Currently we are assuming that both the backlight and LCD are enabled
 | ||||
| // But it's entirely possible to write a custom visualizer that use only
 | ||||
| // one of them
 | ||||
| #ifndef LCD_BACKLIGHT_ENABLE | ||||
| #error This visualizer needs that LCD backlight is enabled | ||||
| #endif | ||||
| 
 | ||||
| #ifndef LCD_ENABLE | ||||
| #error This visualizer needs that LCD is enabled | ||||
| #endif | ||||
| 
 | ||||
| #include "visualizer.h" | ||||
| #include "led_test.h" | ||||
| 
 | ||||
| static const char* welcome_text[] = {"TMK", "Infinity Ergodox"}; | ||||
| 
 | ||||
| // Just an example how to write custom keyframe functions, we could have moved
 | ||||
| // all this into the init function
 | ||||
| bool display_welcome(keyframe_animation_t* animation, visualizer_state_t* state) { | ||||
|     (void)animation; | ||||
|     // Read the uGFX documentation for information how to use the displays
 | ||||
|     // http://wiki.ugfx.org/index.php/Main_Page
 | ||||
|     gdispClear(White); | ||||
|     // You can use static variables for things that can't be found in the animation
 | ||||
|     // or state structs
 | ||||
|     gdispDrawString(0, 3, welcome_text[0], state->font_dejavusansbold12, Black); | ||||
|     gdispDrawString(0, 15, welcome_text[1], state->font_dejavusansbold12, Black); | ||||
|     // Always remember to flush the display
 | ||||
|     gdispFlush(); | ||||
|     // you could set the backlight color as well, but we won't do it here, since
 | ||||
|     // it's part of the following animation
 | ||||
|     // lcd_backlight_color(hue, saturation, intensity);
 | ||||
|     // We don't need constant updates, just drawing the screen once is enough
 | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| // Feel free to modify the animations below, or even add new ones if needed
 | ||||
| 
 | ||||
| // Don't worry, if the startup animation is long, you can use the keyboard like normal
 | ||||
| // during that time
 | ||||
| static keyframe_animation_t startup_animation = { | ||||
|     .num_frames = 4, | ||||
|     .loop = false, | ||||
|     .frame_lengths = {0, gfxMillisecondsToTicks(1000), gfxMillisecondsToTicks(5000), 0}, | ||||
|     .frame_functions = { | ||||
|             display_welcome, | ||||
|             keyframe_animate_backlight_color, | ||||
|             keyframe_no_operation, | ||||
|             enable_visualization | ||||
|     }, | ||||
| }; | ||||
| 
 | ||||
| // The color animation animates the LCD color when you change layers
 | ||||
| static keyframe_animation_t color_animation = { | ||||
|     .num_frames = 2, | ||||
|     .loop = false, | ||||
|     // Note that there's a 200 ms no-operation frame,
 | ||||
|     // this prevents the color from changing when activating the layer
 | ||||
|     // momentarily
 | ||||
|     .frame_lengths = {gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(500)}, | ||||
|     .frame_functions = {keyframe_no_operation, keyframe_animate_backlight_color}, | ||||
| }; | ||||
| 
 | ||||
| // The LCD animation alternates between the layer name display and a
 | ||||
| // bitmap that displays all active layers
 | ||||
| static keyframe_animation_t lcd_animation = { | ||||
|     .num_frames = 2, | ||||
|     .loop = true, | ||||
|     .frame_lengths = {gfxMillisecondsToTicks(2000), gfxMillisecondsToTicks(2000)}, | ||||
|     .frame_functions = {keyframe_display_layer_text, keyframe_display_layer_bitmap}, | ||||
| }; | ||||
| 
 | ||||
| static keyframe_animation_t suspend_animation = { | ||||
|     .num_frames = 3, | ||||
|     .loop = false, | ||||
|     .frame_lengths = {0, gfxMillisecondsToTicks(1000), 0}, | ||||
|     .frame_functions = { | ||||
|             keyframe_display_layer_text, | ||||
|             keyframe_animate_backlight_color, | ||||
|             keyframe_disable_lcd_and_backlight, | ||||
|     }, | ||||
| }; | ||||
| 
 | ||||
| static keyframe_animation_t resume_animation = { | ||||
|     .num_frames = 5, | ||||
|     .loop = false, | ||||
|     .frame_lengths = {0, 0, gfxMillisecondsToTicks(1000), gfxMillisecondsToTicks(5000), 0}, | ||||
|     .frame_functions = { | ||||
|             keyframe_enable_lcd_and_backlight, | ||||
|             display_welcome, | ||||
|             keyframe_animate_backlight_color, | ||||
|             keyframe_no_operation, | ||||
|             enable_visualization, | ||||
|     }, | ||||
| }; | ||||
| 
 | ||||
| void initialize_user_visualizer(visualizer_state_t* state) { | ||||
|     // The brightness will be dynamically adjustable in the future
 | ||||
|     // But for now, change it here.
 | ||||
|     lcd_backlight_brightness(0x50); | ||||
|     state->current_lcd_color = LCD_COLOR(0x00, 0x00, 0xFF); | ||||
|     state->target_lcd_color = LCD_COLOR(0x10, 0xFF, 0xFF); | ||||
|     start_keyframe_animation(&startup_animation); | ||||
|     start_keyframe_animation(&led_test_animation); | ||||
| } | ||||
| 
 | ||||
| void update_user_visualizer_state(visualizer_state_t* state) { | ||||
|     // Add more tests, change the colors and layer texts here
 | ||||
|     // Usually you want to check the high bits (higher layers first)
 | ||||
|     // because that's the order layers are processed for keypresses
 | ||||
|     // You can for check for example:
 | ||||
|     // state->status.layer
 | ||||
|     // state->status.default_layer
 | ||||
|     // state->status.leds (see led.h for available statuses)
 | ||||
|     if (state->status.layer & 0x8) { | ||||
|         state->target_lcd_color = LCD_COLOR(0xC0, 0xB0, 0xFF); | ||||
|         state->layer_text = "Numpad"; | ||||
|     } | ||||
|     else if (state->status.layer & 0x4) { | ||||
|         state->target_lcd_color = LCD_COLOR(0, 0xB0, 0xFF); | ||||
|         state->layer_text = "KBD functions"; | ||||
|     } | ||||
|     else if (state->status.layer & 0x2) { | ||||
|         state->target_lcd_color = LCD_COLOR(0x80, 0xB0, 0xFF); | ||||
|         state->layer_text = "Function keys"; | ||||
|     } | ||||
|     else { | ||||
|         state->target_lcd_color = LCD_COLOR(0x40, 0xB0, 0xFF); | ||||
|         state->layer_text = "Default"; | ||||
|     } | ||||
|     // You can also stop existing animations, and start your custom ones here
 | ||||
|     // remember that you should normally have only one animation for the LCD
 | ||||
|     // and one for the background. But you can also combine them if you want.
 | ||||
|     start_keyframe_animation(&lcd_animation); | ||||
|     start_keyframe_animation(&color_animation); | ||||
| } | ||||
| 
 | ||||
| void user_visualizer_suspend(visualizer_state_t* state) { | ||||
|     state->layer_text = "Suspending..."; | ||||
|     uint8_t hue = LCD_HUE(state->current_lcd_color); | ||||
|     uint8_t sat = LCD_SAT(state->current_lcd_color); | ||||
|     state->target_lcd_color = LCD_COLOR(hue, sat, 0); | ||||
|     start_keyframe_animation(&suspend_animation); | ||||
| } | ||||
| 
 | ||||
| void user_visualizer_resume(visualizer_state_t* state) { | ||||
|     state->current_lcd_color = LCD_COLOR(0x00, 0x00, 0x00); | ||||
|     state->target_lcd_color = LCD_COLOR(0x10, 0xFF, 0xFF); | ||||
|     start_keyframe_animation(&resume_animation); | ||||
|     start_keyframe_animation(&led_test_animation); | ||||
| } | ||||
| @ -0,0 +1,116 @@ | ||||
| #include "satan.h" | ||||
| 
 | ||||
| // Used for SHIFT_ESC
 | ||||
| #define MODS_CTRL_MASK  (MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT)) | ||||
| 
 | ||||
| // Each layer gets a name for readability, which is then used in the keymap matrix below.
 | ||||
| // The underscores don't mean anything - you can have a layer called STUFF or any other name.
 | ||||
| // Layer names don't all need to be of the same length, obviously, and you can also skip them
 | ||||
| // entirely and just use numbers.
 | ||||
| #define _BL 0 | ||||
| #define _FL 1 | ||||
| #define _RL 2 | ||||
| 
 | ||||
| const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | ||||
|   /* Keymap _BL: (Base Layer) Default Layer
 | ||||
|    * ,-----------------------------------------------------------. | ||||
|    * |Esc~| 1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|Backsp | | ||||
|    * |-----------------------------------------------------------| | ||||
|    * |Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|  \  | | ||||
|    * |-----------------------------------------------------------| | ||||
|    * |CAPS   |  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;|  '|Return | | ||||
|    * |-----------------------------------------------------------| | ||||
|    * |Shift   |  Z|  X|  C|  V|  B|  N|  M|  ,|  .|  /|Shift     | | ||||
|    * |-----------------------------------------------------------| | ||||
|    * |Ctrl|Gui |Alt |      Space            |Alt |Gui |FN  |Ctrl | | ||||
|    * `-----------------------------------------------------------' | ||||
|    */ | ||||
| [_BL] = KEYMAP( | ||||
|   F(0),    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_BSPC, \ | ||||
|   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_BSLS, \ | ||||
|   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_ENT,  \ | ||||
|   KC_LSFT,         KC_Z,   KC_X,   KC_C,   KC_V,   KC_B,   KC_N,   KC_M,   KC_COMM,KC_DOT, KC_SLSH,            KC_RSFT, \ | ||||
|   KC_LCTL, KC_LGUI,KC_LALT,          KC_SPC,                                        KC_RALT,  MO(_RL), MO(_FL),  KC_RCTL), | ||||
| 
 | ||||
| /* Keymap _FL: Function Layer
 | ||||
|    * ,-----------------------------------------------------------. | ||||
|    * | ~ | F1|F2 |F3 |F4 |F5 |F6 |F7 |F8 |F9 |F10|F11|F12|  DEL  | | ||||
|    * |-----------------------------------------------------------| | ||||
|    * |     | Up|  |  |  |  |Cal|   |Ins|   |PrSc|Sclk|Paus|      | | ||||
|    * |-----------------------------------------------------------| | ||||
|    * |      |Left|Down|Rig|  |  |  |  |   |   |Home|PgUp|        | | ||||
|    * |-----------------------------------------------------------| | ||||
|    * |        |   |App|  |  |   |Vdn|Vup|Mute|End|PgDn|          | | ||||
|    * |-----------------------------------------------------------| | ||||
|    * |    |    |    |                        |    |    |    |    | | ||||
|    * `-----------------------------------------------------------' | ||||
|    */ | ||||
| [_FL] = KEYMAP( | ||||
|   KC_GRV, 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_DEL,  \ | ||||
|   KC_TRNS,KC_TRNS, KC_UP,  KC_TRNS,KC_TRNS,KC_TRNS, KC_CALC,KC_TRNS,KC_INS, KC_TRNS, KC_PSCR,  KC_SLCK,   KC_PAUS,   KC_TRNS, \ | ||||
|   KC_TRNS,KC_LEFT,KC_DOWN,KC_RGHT,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_HOME,    KC_PGUP,              KC_TRNS, \ | ||||
|   KC_TRNS, KC_TRNS,  KC_APP,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_VOLD,  KC_VOLU, KC_MUTE, KC_END, KC_PGDN, KC_TRNS, \ | ||||
|   KC_TRNS,KC_TRNS,KC_TRNS,          KC_TRNS,                               KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS), | ||||
|    | ||||
|   /* Keymap _RL: Function Layer
 | ||||
|    * ,-----------------------------------------------------------. | ||||
|    * |   |   |   |   |   |   |   |   |   |   |   |   |   |  RESET| | ||||
|    * |-----------------------------------------------------------| | ||||
|    * |     |   |   |   |   |   |   |   |   |   |   |BL-|BL+|BL   | | ||||
|    * |-----------------------------------------------------------| | ||||
|    * |      |   |   |   |   |   |   |       |   |   |   |        | | ||||
|    * |-----------------------------------------------------------| | ||||
|    * |        | F1|F2 | F3|F4 | F5| F6| F7| F8|   |   |          | | ||||
|    * |-----------------------------------------------------------| | ||||
|    * |    |    |    |                        |    |    |    |    | | ||||
|    * `-----------------------------------------------------------'    | ||||
|    */ | ||||
| [_RL] = KEYMAP( | ||||
|   #ifdef RGBLIGHT_ENABLE | ||||
|   KC_GRV, KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RESET,  \ | ||||
|   KC_TRNS,KC_TRNS,KC_TRNS,  KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS,   KC_TRNS,   BL_DEC,   BL_INC,   BL_TOGG, \ | ||||
|   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, RGB_TOG,RGB_MOD,RGB_HUI,RGB_HUD,RGB_SAI,RGB_SAD,RGB_VAI,RGB_VAD, KC_TRNS, KC_TRNS, KC_TRNS, \ | ||||
|   KC_TRNS,KC_TRNS,KC_TRNS,          KC_TRNS,                               KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS), | ||||
|   #else | ||||
|   KC_GRV, KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RESET,  \ | ||||
|   KC_TRNS,KC_TRNS,KC_TRNS,  KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS,   KC_TRNS,   BL_DEC,   BL_INC,   BL_TOGG, \ | ||||
|   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_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), | ||||
|   #endif | ||||
| }; | ||||
| 
 | ||||
| enum function_id { | ||||
|     SHIFT_ESC, | ||||
| }; | ||||
| 
 | ||||
| const uint16_t PROGMEM fn_actions[] = { | ||||
|   [0]  = ACTION_FUNCTION(SHIFT_ESC), | ||||
| }; | ||||
| 
 | ||||
| void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { | ||||
|   static uint8_t shift_esc_shift_mask; | ||||
|   switch (id) { | ||||
|     case SHIFT_ESC: | ||||
|       shift_esc_shift_mask = get_mods()&MODS_CTRL_MASK; | ||||
|       if (record->event.pressed) { | ||||
|         if (shift_esc_shift_mask) { | ||||
|           add_key(KC_GRV); | ||||
|           send_keyboard_report(); | ||||
|         } else { | ||||
|           add_key(KC_ESC); | ||||
|           send_keyboard_report(); | ||||
|         } | ||||
|       } else { | ||||
|         if (shift_esc_shift_mask) { | ||||
|           del_key(KC_GRV); | ||||
|           send_keyboard_report(); | ||||
|         } else { | ||||
|           del_key(KC_ESC); | ||||
|           send_keyboard_report(); | ||||
|         } | ||||
|       } | ||||
|       break; | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,20 @@ | ||||
| #include "../../config.h" | ||||
| 
 | ||||
| // USB Device descriptor parameter
 | ||||
| #define VENDOR_ID       0xFEED | ||||
| #define PRODUCT_ID      0x6060 | ||||
| #define DEVICE_VER      0x0003 | ||||
| #define MANUFACTURER    Custom | ||||
| #define PRODUCT         GH60 rev.CHN | ||||
| #define DESCRIPTION     QMK keyboard firmware for GH60 with WS2812 support | ||||
| 
 | ||||
| // Backlight configuration
 | ||||
| #define BACKLIGHT_LEVELS 3 | ||||
| 
 | ||||
| // Underlight configuration
 | ||||
| #define RGB_DI_PIN E2 | ||||
| #define RGBLIGHT_TIMER | ||||
| #define RGBLED_NUM 6        // Number of LEDs
 | ||||
| #define RGBLIGHT_HUE_STEP 8 | ||||
| #define RGBLIGHT_SAT_STEP 8 | ||||
| #define RGBLIGHT_VAL_STEP 8 | ||||
| @ -0,0 +1,84 @@ | ||||
| #include "satan.h" | ||||
| 
 | ||||
| // Used for SHIFT_ESC
 | ||||
| #define MODS_CTRL_MASK  (MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT)) | ||||
| 
 | ||||
| // Each layer gets a name for readability, which is then used in the keymap matrix below.
 | ||||
| // The underscores don't mean anything - you can have a layer called STUFF or any other name.
 | ||||
| // Layer names don't all need to be of the same length, obviously, and you can also skip them
 | ||||
| // entirely and just use numbers.
 | ||||
| #define _BL   0 | ||||
| #define _FL   1 | ||||
| #define _RGBL 2 | ||||
| 
 | ||||
| const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | ||||
| 
 | ||||
| // See base_layer.png and rgb_layer.png for layout reference
 | ||||
| 
 | ||||
| // Base Default Layer
 | ||||
| // Mac Modifier Layout. Use BootMagic to toggle GUI and ALT positions.
 | ||||
| [_BL] = KEYMAP_HHKB( | ||||
|   F(0),             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_BSPC, KC_NO, \ | ||||
|   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_BSLS,       \ | ||||
|   LT(_FL, 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_ENT,        \ | ||||
|   KC_LSFT,          KC_Z,   KC_X,   KC_C,   KC_V,   KC_B,   KC_N,   KC_M,   KC_COMM, KC_DOT, KC_SLSH,           KC_UP,    MO(_FL),       \ | ||||
|   KC_LCTL, KC_LALT, KC_LGUI,                        KC_SPC,                                  KC_RGUI, KC_LEFT,  KC_DOWN,  KC_RGHT), | ||||
| 
 | ||||
| // Function layer
 | ||||
| [_FL] = KEYMAP_HHKB( | ||||
|   KC_GRV,  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_DEL, KC_NO, \ | ||||
|   KC_NO,   KC_MPRV, KC_UP,   KC_MNXT, KC_NO,   KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_PSCR, KC_SLCK, KC_PAUS, KC_INS, \ | ||||
|   KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_NO,   KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,   KC_NO,            KC_NO,  \ | ||||
|   KC_TRNS,          KC_MUTE, KC_VOLD, KC_VOLU, KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,   KC_NO,   LT(_RGBL, KC_PGUP), KC_TRNS,  \ | ||||
|   KC_TRNS, KC_TRNS, KC_TRNS,                           KC_MPLY,                                 KC_TRNS, KC_HOME, KC_PGDN, KC_END), | ||||
| 
 | ||||
| // RGB Layer
 | ||||
| [_RGBL] = KEYMAP_HHKB( | ||||
|   #ifdef RGBLIGHT_ENABLE | ||||
|   RESET,   KC_NO,   KC_NO,   KC_NO,   KC_NO,   KC_NO,   KC_NO,   KC_NO,   KC_NO,   KC_NO,    KC_NO,   KC_NO,   KC_NO,   KC_NO, KC_NO, \ | ||||
|   KC_NO,   KC_NO,   KC_NO,   KC_NO,   KC_NO,   KC_NO,   KC_NO,   KC_NO,   KC_NO,   KC_NO,    KC_NO,   KC_NO,   KC_NO,   KC_NO, \ | ||||
|   KC_NO,   BL_TOGG, BL_STEP, KC_NO,   KC_NO,   KC_NO,   KC_NO,   KC_NO,   KC_NO,   KC_NO,    KC_NO,   KC_NO,            KC_NO,  \ | ||||
|   KC_TRNS,          RGB_TOG, RGB_MOD, RGB_HUI, RGB_HUD, RGB_SAI, RGB_SAD, RGB_VAI, RGB_VAD,  KC_NO,   KC_NO,   KC_TRNS, KC_TRNS,\ | ||||
|   KC_TRNS, KC_TRNS, KC_TRNS,                            KC_TRNS,                             KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS), | ||||
|   #else | ||||
|   RESET,   KC_NO,   KC_NO,   KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,   KC_NO,   KC_NO,   KC_NO, KC_NO, \ | ||||
|   KC_NO,   KC_NO,   KC_NO,   KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,   KC_NO,   KC_NO,   KC_NO, \ | ||||
|   KC_NO,   BL_TOGG, BL_STEP, KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,   KC_NO,            KC_NO,  \ | ||||
|   KC_TRNS,          KC_NO,   KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,   KC_NO,   KC_TRNS, KC_TRNS,\ | ||||
|   KC_TRNS, KC_TRNS, KC_TRNS,                         KC_TRNS,                        KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS), | ||||
|   #endif | ||||
| }; | ||||
| 
 | ||||
| enum function_id { | ||||
|     SHIFT_ESC, | ||||
| }; | ||||
| 
 | ||||
| const uint16_t PROGMEM fn_actions[] = { | ||||
|   [0]  = ACTION_FUNCTION(SHIFT_ESC), | ||||
| }; | ||||
| 
 | ||||
| void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { | ||||
|   static uint8_t shift_esc_shift_mask; | ||||
|   switch (id) { | ||||
|     case SHIFT_ESC: | ||||
|       shift_esc_shift_mask = get_mods()&MODS_CTRL_MASK; | ||||
|       if (record->event.pressed) { | ||||
|         if (shift_esc_shift_mask) { | ||||
|           add_key(KC_GRV); | ||||
|           send_keyboard_report(); | ||||
|         } else { | ||||
|           add_key(KC_ESC); | ||||
|           send_keyboard_report(); | ||||
|         } | ||||
|       } else { | ||||
|         if (shift_esc_shift_mask) { | ||||
|           del_key(KC_GRV); | ||||
|           send_keyboard_report(); | ||||
|         } else { | ||||
|           del_key(KC_ESC); | ||||
|           send_keyboard_report(); | ||||
|         } | ||||
|       } | ||||
|       break; | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1 @@ | ||||
| Subproject commit 13e084ae6231857cd0d472c529f34be07d93c08b | ||||
					Loading…
					
					
				
		Reference in new issue
	
	 Joshua Colbeck
						Joshua Colbeck