Add Satisfaction75 to QMK, Enable EEPROM on stm32f072 (#5094)

* Add stm32f072 base ck4x4 to handwired

* add prints

* Save these tries

* Save changes again

* Working hadron oled

* OLEd working but ws2812b still iffy:

* save another try

* Encoder feature + OLED

* RTC code

* Implement clock setting mode

* Whitespace

* Encoder hooked up to working LED PWM code

* Add missing files

* eeprom changes

* Save changes

* Move i2c master

* Move satisfaction75 under cannonkeys

* Set proper default folder

* Revert some core changes

* Undo paved iris changes

* Reorganize code for maintainability and prep for new features

* Add starting code for clock OLED mode

* Clock set mode finished

* Add custom encoder modes

* Actually add VIA keymap

* Gate to only 072

* fix gate for only 072

* Update header guards and includes

* Update i2c selection strategy

* Update board.c to handle software reset to DFU
This commit is contained in:
Andrew Kannan
2019-02-13 11:03:26 -05:00
committed by MechMerlin
parent 824aa06c3c
commit 6b4549da8c
37 changed files with 5630 additions and 5 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
.history/
.dep
*.o
*.bin

View File

@ -28,6 +28,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "micro_oled.h"
#include <print.h>
#include <stdlib.h>
#include "util/font5x7.h"
#include "util/font8x16.h"
@ -314,7 +315,6 @@ static uint8_t micro_oled_screen_buffer[] = {
void micro_oled_init(void) {
i2c_init();
i2c_start(I2C_ADDRESS_SA0_1);

View File

@ -0,0 +1,111 @@
/*
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
* This file has been automatically generated using ChibiStudio board
* generator plugin. Do not edit manually.
*/
#include "hal.h"
#if HAL_USE_PAL || defined(__DOXYGEN__)
/**
* @brief PAL setup.
* @details Digital I/O ports static configuration as defined in @p board.h.
* This variable is used by the HAL when initializing the PAL driver.
*/
const PALConfig pal_default_config = {
#if STM32_HAS_GPIOA
{VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR,
VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH},
#endif
#if STM32_HAS_GPIOB
{VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR,
VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH},
#endif
#if STM32_HAS_GPIOC
{VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR,
VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH},
#endif
#if STM32_HAS_GPIOD
{VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR,
VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH},
#endif
#if STM32_HAS_GPIOE
{VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR,
VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH},
#endif
#if STM32_HAS_GPIOF
{VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR,
VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH},
#endif
#if STM32_HAS_GPIOG
{VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR,
VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH},
#endif
#if STM32_HAS_GPIOH
{VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR,
VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH},
#endif
#if STM32_HAS_GPIOI
{VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR,
VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH}
#endif
};
#endif
void enter_bootloader_mode_if_requested(void);
/**
* @brief Early initialization code.
* @details This initialization must be performed just after stack setup
* and before any other initialization.
*/
void __early_init(void) {
enter_bootloader_mode_if_requested();
stm32_clock_init();
}
#if HAL_USE_MMC_SPI || defined(__DOXYGEN__)
/**
* @brief MMC_SPI card detection.
*/
bool mmc_lld_is_card_inserted(MMCDriver *mmcp) {
(void)mmcp;
/* TODO: Fill the implementation.*/
return true;
}
/**
* @brief MMC_SPI card write protection detection.
*/
bool mmc_lld_is_write_protected(MMCDriver *mmcp) {
(void)mmcp;
/* TODO: Fill the implementation.*/
return false;
}
#endif
/**
* @brief Board-specific initialization code.
* @todo Add your board-specific code, if any.
*/
void boardInit(void) {
SYSCFG->CFGR1 |= SYSCFG_CFGR1_I2C1_DMA_RMP;
SYSCFG->CFGR1 &= ~(SYSCFG_CFGR1_SPI2_DMA_RMP);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,5 @@
# List of all the board related files.
BOARDSRC = $(BOARD_PATH)/boards/ST_STM32F072B_DISCOVERY/board.c
# Required include directories
BOARDINC = $(BOARD_PATH)/boards/ST_STM32F072B_DISCOVERY

View File

@ -0,0 +1,7 @@
/* Address for jumping to bootloader on STM32 chips. */
/* It is chip dependent, the correct number can be looked up here (page 175):
* http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf
* This also requires a patch to chibios:
* <tmk_dir>/tmk_core/tool/chibios/ch-bootloader-jump.patch
*/
#define STM32_BOOTLOADER_ADDRESS 0x1FFFC800

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,107 @@
/*
Copyright 2015 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/>.
*/
#pragma once
/* USB Device descriptor parameter */
#define VENDOR_ID 0xCA04
#define PRODUCT_ID 0x57F5
#define DEVICE_VER 0x0001
/* in python2: list(u"whatever".encode('utf-16-le')) */
/* at most 32 characters or the ugly hack in usb_main.c borks */
#define MANUFACTURER QMK
#define PRODUCT Satisfaction75
#define DESCRIPTION Satisfaction 75 Keyboard
/* key matrix size */
#define MATRIX_ROWS 6
#define MATRIX_COLS 16
#define MATRIX_COL_PINS { B1, B2, B10, B11, B12, B13, B14, A8, A9, A10, B0, A7, A5, B5, A15, A1 }
#define MATRIX_ROW_PINS { B3, B4, A0, A2, A4, A3 }
#define DIODE_DIRECTION COL2ROW
#define NUMBER_OF_ENCODERS 1
#define ENCODERS_PAD_A { B9 }
#define ENCODERS_PAD_B { B8 }
//LEDS A6, RGB B15
#define BACKLIGHT_LEVELS 24
#define BACKLIGHT_BREATHING
#define BREATHING_PERIOD 6
/* define if matrix has ghost */
//#define MATRIX_HAS_GHOST
/* Set 0 if debouncing isn't needed */
#define DEBOUNCE 5
/* 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
#ifdef QWIIC_MICRO_OLED_ENABLE
#undef I2C_ADDRESS_SA0_1
#define I2C_ADDRESS_SA0_1 0b0111100
#define LCDWIDTH 128
#define LCDHEIGHT 32
#endif
#define DYNAMIC_KEYMAP_LAYER_COUNT 4
// EEPROM usage
// TODO: refactor with new user EEPROM code (coming soon)
#define EEPROM_MAGIC 0x451F
#define EEPROM_MAGIC_ADDR 32
// Bump this every time we change what we store
// This will automatically reset the EEPROM with defaults
// and avoid loading invalid data from the EEPROM
#define EEPROM_VERSION 0x02
#define EEPROM_VERSION_ADDR 34
// Dynamic keymap starts after EEPROM version
#define DYNAMIC_KEYMAP_EEPROM_ADDR 35
// Dynamic macro starts after dynamic keymaps (35+(4*6*16*2)) = (35+768)
#define DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR 803
#define DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE 221
#define DYNAMIC_KEYMAP_MACRO_COUNT 16
/*
* 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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,116 @@
/* Copyright 2018 Jack Humbert
* Copyright 2018 Yiancar
*
* 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/>.
*/
/* This library is only valid for STM32 processors.
* This library follows the convention of the AVR i2c_master library.
* As a result addresses are expected to be already shifted (addr << 1).
* I2CD1 is the default driver which corresponds to pins B6 and B7. This
* can be changed.
* Please ensure that HAL_USE_I2C is TRUE in the halconf.h file and that
* STM32_I2C_USE_I2C1 is TRUE in the mcuconf.h file. Pins B6 and B7 are used
* but using any other I2C pins should be trivial.
*/
#include "i2c_master.h"
#include "quantum.h"
#include <string.h>
#include <hal.h>
#include "chtypes.h"
#include "ch.h"
static uint8_t i2c_address;
// This configures the I2C clock to 400khz assuming a 48Mhz clock
// For more info : https://www.st.com/en/embedded-software/stsw-stm32126.html
static const I2CConfig i2cconfig = {
STM32_TIMINGR_PRESC(0x00U) |
STM32_TIMINGR_SCLDEL(0x03U) | STM32_TIMINGR_SDADEL(0x01U) |
STM32_TIMINGR_SCLH(0x03U) | STM32_TIMINGR_SCLL(0x09U),
0,
0
};
__attribute__ ((weak))
void i2c_init(void)
{
// Try releasing special pins for a short time
palSetPadMode(GPIOB, 6, PAL_MODE_INPUT);
palSetPadMode(GPIOB, 7, PAL_MODE_INPUT);
chThdSleepMilliseconds(10);
palSetPadMode(GPIOB, 6, PAL_MODE_ALTERNATE(1) | PAL_STM32_OTYPE_OPENDRAIN);
palSetPadMode(GPIOB, 7, PAL_MODE_ALTERNATE(1) | PAL_STM32_OTYPE_OPENDRAIN);
//i2cInit(); //This is invoked by halInit() so no need to redo it.
}
// This is usually not needed
uint8_t i2c_start(uint8_t address)
{
i2c_address = address;
i2cStart(&I2C_DRIVER, &i2cconfig);
return 0;
}
uint8_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout)
{
msg_t status = MSG_OK;
i2c_address = address;
i2cStart(&I2C_DRIVER, &i2cconfig);
i2cAcquireBus(&I2C_DRIVER);
status = i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), data, length, 0, 0, MS2ST(timeout));
i2cReleaseBus(&I2C_DRIVER);
return status;
}
uint8_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout)
{
i2c_address = address;
i2cStart(&I2C_DRIVER, &i2cconfig);
return i2cMasterReceiveTimeout(&I2C_DRIVER, (i2c_address >> 1), data, length, MS2ST(timeout));
}
uint8_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)
{
i2c_address = devaddr;
i2cStart(&I2C_DRIVER, &i2cconfig);
uint8_t complete_packet[length + 1];
for(uint8_t i = 0; i < length; i++)
{
complete_packet[i+1] = data[i];
}
complete_packet[0] = regaddr;
return i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), complete_packet, length + 1, 0, 0, MS2ST(timeout));
}
uint8_t i2c_readReg(uint8_t devaddr, uint8_t* regaddr, uint8_t* data, uint16_t length, uint16_t timeout)
{
i2c_address = devaddr;
i2cStart(&I2C_DRIVER, &i2cconfig);
return i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), regaddr, 1, data, length, MS2ST(timeout));
}
// This is usually not needed. It releases the driver to allow pins to become GPIO again.
uint8_t i2c_stop(uint16_t timeout)
{
i2cStop(&I2C_DRIVER);
return 0;
}

View File

@ -0,0 +1,37 @@
/*
Copyright 2012,2013 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/>.
*/
#include QMK_KEYBOARD_H
const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT_default(
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12,
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, ENC_PRESS,
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_DEL,
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_ENTER, KC_PGUP,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_PGDN,
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT
),
[1] = LAYOUT_default(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, OLED_TOGG,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, CLOCK_SET,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______
)
};

View File

@ -0,0 +1,49 @@
/*
Copyright 2012,2013 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/>.
*/
#include QMK_KEYBOARD_H
const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT_default(
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12,
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, ENC_PRESS,
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_DEL,
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_ENTER, KC_PGUP,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_PGDN,
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT
),
[1] = LAYOUT_default(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, OLED_TOGG,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, CLOCK_SET,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______
)
};
void matrix_init_user(void) {
//user initialization
}
void matrix_scan_user(void) {
//user matrix
}
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
return true;
}

View File

@ -0,0 +1,5 @@
# rules.mk overrides to enable VIA
RAW_ENABLE = yes
DYNAMIC_KEYMAP_ENABLE = yes

View File

@ -0,0 +1,240 @@
/*
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/>.
*/
#include "hal.h"
#include "led_custom.h"
#include "satisfaction75.h"
#include "printf.h"
static void breathing_callback(PWMDriver *pwmp);
static PWMConfig pwmCFG = {
0xFFFF, /* PWM clock frequency */
256, /* PWM period (in ticks) 1S (1/10kHz=0.1mS 0.1ms*10000 ticks=1S) */
NULL, /* No Callback */
{
{PWM_OUTPUT_ACTIVE_HIGH, NULL}, /* Enable Channel 0 */
{PWM_OUTPUT_DISABLED, NULL},
{PWM_OUTPUT_DISABLED, NULL},
{PWM_OUTPUT_DISABLED, NULL}
},
0, /* HW dependent part.*/
0
};
static PWMConfig pwmCFG_breathing = {
0xFFFF, /* 10kHz PWM clock frequency */
256, /* PWM period (in ticks) 1S (1/10kHz=0.1mS 0.1ms*10000 ticks=1S) */
breathing_callback, /* Breathing Callback */
{
{PWM_OUTPUT_ACTIVE_HIGH, NULL}, /* Enable Channel 0 */
{PWM_OUTPUT_DISABLED, NULL},
{PWM_OUTPUT_DISABLED, NULL},
{PWM_OUTPUT_DISABLED, NULL}
},
0, /* HW dependent part.*/
0
};
// See http://jared.geek.nz/2013/feb/linear-led-pwm
static uint16_t cie_lightness(uint16_t v) {
if (v <= 5243) // if below 8% of max
return v / 9; // same as dividing by 900%
else {
uint32_t y = (((uint32_t) v + 10486) << 8) / (10486 + 0xFFFFUL); // add 16% of max and compare
// to get a useful result with integer division, we shift left in the expression above
// and revert what we've done again after squaring.
y = y * y * y >> 8;
if (y > 0xFFFFUL) // prevent overflow
return 0xFFFFU;
else
return (uint16_t) y;
}
}
void backlight_init_ports(void) {
palSetPadMode(GPIOA, 6, PAL_MODE_ALTERNATE(1));
pwmStart(&PWMD3, &pwmCFG);
if(kb_backlight_config.enable){
if(kb_backlight_config.breathing){
breathing_enable();
} else{
backlight_set(kb_backlight_config.level);
}
} else {
backlight_set(0);
}
}
void backlight_set(uint8_t level) {
uint32_t duty = (uint32_t)(cie_lightness(0xFFFF * (uint32_t) level / BACKLIGHT_LEVELS));
if (level == 0) {
// Turn backlight off
pwmDisableChannel(&PWMD3, 0);
} else {
// Turn backlight on
if(!is_breathing()){
pwmEnableChannel(&PWMD3, 0, PWM_FRACTION_TO_WIDTH(&PWMD3,0xFFFF,duty));
}
}
}
uint8_t backlight_tick = 0;
void backlight_task(void) {
}
#define BREATHING_NO_HALT 0
#define BREATHING_HALT_OFF 1
#define BREATHING_HALT_ON 2
#define BREATHING_STEPS 128
static uint8_t breathing_period = BREATHING_PERIOD;
static uint8_t breathing_halt = BREATHING_NO_HALT;
static uint16_t breathing_counter = 0;
bool is_breathing(void) {
return PWMD3.config == &pwmCFG_breathing;
}
#define breathing_min() do {breathing_counter = 0;} while (0)
#define breathing_max() do {breathing_counter = breathing_period * 256 / 2;} while (0)
void breathing_interrupt_enable(void){
pwmStop(&PWMD3);
pwmStart(&PWMD3, &pwmCFG_breathing);
chSysLockFromISR();
pwmEnablePeriodicNotification(&PWMD3);
pwmEnableChannelI(
&PWMD3,
0,
PWM_FRACTION_TO_WIDTH(
&PWMD3,
0xFFFF,
0xFFFF
)
);
chSysUnlockFromISR();
}
void breathing_interrupt_disable(void){
pwmStop(&PWMD3);
pwmStart(&PWMD3, &pwmCFG);
}
void breathing_enable(void)
{
breathing_counter = 0;
breathing_halt = BREATHING_NO_HALT;
breathing_interrupt_enable();
}
void breathing_pulse(void)
{
if (kb_backlight_config.level == 0)
breathing_min();
else
breathing_max();
breathing_halt = BREATHING_HALT_ON;
breathing_interrupt_enable();
}
void breathing_disable(void)
{
breathing_interrupt_disable();
// Restore backlight level
backlight_set(kb_backlight_config.level);
}
void breathing_self_disable(void)
{
if (kb_backlight_config.level == 0)
breathing_halt = BREATHING_HALT_OFF;
else
breathing_halt = BREATHING_HALT_ON;
}
void breathing_toggle(void) {
if (is_breathing()){
breathing_disable();
} else {
breathing_enable();
}
}
void breathing_period_set(uint8_t value)
{
if (!value)
value = 1;
breathing_period = value;
}
void breathing_period_default(void) {
breathing_period_set(BREATHING_PERIOD);
}
void breathing_period_inc(void)
{
breathing_period_set(breathing_period+1);
}
void breathing_period_dec(void)
{
breathing_period_set(breathing_period-1);
}
/* To generate breathing curve in python:
* from math import sin, pi; [int(sin(x/128.0*pi)**4*255) for x in range(128)]
*/
static const uint8_t breathing_table[BREATHING_STEPS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 17, 20, 24, 28, 32, 36, 41, 46, 51, 57, 63, 70, 76, 83, 91, 98, 106, 113, 121, 129, 138, 146, 154, 162, 170, 178, 185, 193, 200, 207, 213, 220, 225, 231, 235, 240, 244, 247, 250, 252, 253, 254, 255, 254, 253, 252, 250, 247, 244, 240, 235, 231, 225, 220, 213, 207, 200, 193, 185, 178, 170, 162, 154, 146, 138, 129, 121, 113, 106, 98, 91, 83, 76, 70, 63, 57, 51, 46, 41, 36, 32, 28, 24, 20, 17, 15, 12, 10, 8, 6, 5, 4, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
// Use this before the cie_lightness function.
static inline uint16_t scale_backlight(uint16_t v) {
return v / BACKLIGHT_LEVELS * kb_backlight_config.level;
}
static void breathing_callback(PWMDriver *pwmp)
{
(void)pwmp;
uint16_t interval = (uint16_t) breathing_period * 256 / BREATHING_STEPS;
// resetting after one period to prevent ugly reset at overflow.
breathing_counter = (breathing_counter + 1) % (breathing_period * 256);
uint8_t index = breathing_counter / interval % BREATHING_STEPS;
if (((breathing_halt == BREATHING_HALT_ON) && (index == BREATHING_STEPS / 2)) ||
((breathing_halt == BREATHING_HALT_OFF) && (index == BREATHING_STEPS - 1)))
{
breathing_interrupt_disable();
}
uint32_t duty = cie_lightness(scale_backlight(breathing_table[index] * 256));
chSysLockFromISR();
pwmEnableChannelI(
&PWMD3,
0,
PWM_FRACTION_TO_WIDTH(
&PWMD3,
0xFFFF,
duty
)
);
chSysUnlockFromISR();
}

View File

@ -0,0 +1,5 @@
#pragma once
void backlight_task(void);
void breathing_interrupt_disable(void);
void breathing_interrupt_enable(void);

View File

@ -0,0 +1,176 @@
/*
ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef _MCUCONF_H_
#define _MCUCONF_H_
/*
* STM32F0xx drivers configuration.
* The following settings override the default settings present in
* the various device driver implementation headers.
* Note that the settings for each driver only have effect if the whole
* driver is enabled in halconf.h.
*
* IRQ priorities:
* 3...0 Lowest...Highest.
*
* DMA priorities:
* 0...3 Lowest...Highest.
*/
#define STM32F0xx_MCUCONF
// #define STM32F070xB
/*
* HAL driver system settings.
*/
#define STM32_NO_INIT FALSE
#define STM32_PVD_ENABLE FALSE
#define STM32_PLS STM32_PLS_LEV0
#define STM32_HSI_ENABLED TRUE
#define STM32_HSI14_ENABLED TRUE
#define STM32_HSI48_ENABLED FALSE
#define STM32_LSI_ENABLED TRUE
#define STM32_HSE_ENABLED FALSE
#define STM32_LSE_ENABLED TRUE
#define STM32_SW STM32_SW_PLL
#define STM32_PLLSRC STM32_PLLSRC_HSI_DIV2
#define STM32_PREDIV_VALUE 1
#define STM32_PLLMUL_VALUE 12
#define STM32_HPRE STM32_HPRE_DIV1
#define STM32_PPRE STM32_PPRE_DIV1
#define STM32_ADCSW STM32_ADCSW_HSI14
#define STM32_ADCPRE STM32_ADCPRE_DIV4
#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK
#define STM32_ADCPRE STM32_ADCPRE_DIV4
#define STM32_ADCSW STM32_ADCSW_HSI14
#define STM32_USBSW STM32_USBSW_HSI48
#define STM32_CECSW STM32_CECSW_HSI
#define STM32_I2C1SW STM32_I2C1SW_HSI
#define STM32_USART1SW STM32_USART1SW_PCLK
#define STM32_RTCSEL STM32_RTCSEL_LSE
/*
* ADC driver system settings.
*/
#define STM32_ADC_USE_ADC1 FALSE
#define STM32_ADC_ADC1_DMA_PRIORITY 2
#define STM32_ADC_IRQ_PRIORITY 2
#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 2
/*
* EXT driver system settings.
*/
#define STM32_EXT_EXTI0_1_IRQ_PRIORITY 3
#define STM32_EXT_EXTI2_3_IRQ_PRIORITY 3
#define STM32_EXT_EXTI4_15_IRQ_PRIORITY 3
#define STM32_EXT_EXTI16_IRQ_PRIORITY 3
#define STM32_EXT_EXTI17_IRQ_PRIORITY 3
/*
* GPT driver system settings.
*/
#define STM32_GPT_USE_TIM1 FALSE
#define STM32_GPT_USE_TIM2 FALSE
#define STM32_GPT_USE_TIM3 FALSE
#define STM32_GPT_USE_TIM14 FALSE
#define STM32_GPT_TIM1_IRQ_PRIORITY 2
#define STM32_GPT_TIM2_IRQ_PRIORITY 2
#define STM32_GPT_TIM3_IRQ_PRIORITY 2
#define STM32_GPT_TIM14_IRQ_PRIORITY 2
/*
* I2C driver system settings.
*/
#define STM32_I2C_USE_I2C1 TRUE
#define STM32_I2C_USE_I2C2 FALSE
#define STM32_I2C_BUSY_TIMEOUT 50
#define STM32_I2C_I2C1_IRQ_PRIORITY 3
#define STM32_I2C_I2C2_IRQ_PRIORITY 3
#define STM32_I2C_USE_DMA TRUE
#define STM32_I2C_I2C1_DMA_PRIORITY 1
#define STM32_I2C_I2C2_DMA_PRIORITY 1
#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7)
#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure")
/*
* ICU driver system settings.
*/
#define STM32_ICU_USE_TIM1 FALSE
#define STM32_ICU_USE_TIM2 FALSE
#define STM32_ICU_USE_TIM3 FALSE
#define STM32_ICU_TIM1_IRQ_PRIORITY 3
#define STM32_ICU_TIM2_IRQ_PRIORITY 3
#define STM32_ICU_TIM3_IRQ_PRIORITY 3
/*
* PWM driver system settings.
*/
#define STM32_PWM_USE_ADVANCED FALSE
#define STM32_PWM_USE_TIM1 FALSE
#define STM32_PWM_USE_TIM2 FALSE
#define STM32_PWM_USE_TIM3 TRUE
#define STM32_PWM_TIM1_IRQ_PRIORITY 3
#define STM32_PWM_TIM2_IRQ_PRIORITY 3
#define STM32_PWM_TIM3_IRQ_PRIORITY 3
/*
* SERIAL driver system settings.
*/
#define STM32_SERIAL_USE_USART1 FALSE
#define STM32_SERIAL_USE_USART2 FALSE
#define STM32_SERIAL_USART1_PRIORITY 3
#define STM32_SERIAL_USART2_PRIORITY 3
/*
* SPI driver system settings.
*/
#define STM32_SPI_USE_SPI1 FALSE
#define STM32_SPI_USE_SPI2 TRUE
#define STM32_SPI_SPI1_DMA_PRIORITY 1
#define STM32_SPI_SPI2_DMA_PRIORITY 1
#define STM32_SPI_SPI1_IRQ_PRIORITY 2
#define STM32_SPI_SPI2_IRQ_PRIORITY 2
#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4)
#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5)
#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
/*
* ST driver system settings.
*/
#define STM32_ST_IRQ_PRIORITY 2
#define STM32_ST_USE_TIMER 2
/*
* UART driver system settings.
*/
#define STM32_UART_USE_USART1 FALSE
#define STM32_UART_USE_USART2 FALSE
#define STM32_UART_USART1_IRQ_PRIORITY 3
#define STM32_UART_USART2_IRQ_PRIORITY 3
#define STM32_UART_USART1_DMA_PRIORITY 0
#define STM32_UART_USART2_DMA_PRIORITY 0
#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure")
/*
* USB driver system settings.
*/
#define STM32_USB_USE_USB1 TRUE
#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE
#define STM32_USB_USB1_LP_IRQ_PRIORITY 3
#endif /* _MCUCONF_H_ */

View File

@ -0,0 +1,12 @@
# Satisfaction75
Satisfaction75 Keyboard
Keyboard Maintainer: [Andrew Kannan](https://github.com/awkannan1)
Hardware Supported: STM32F072CBT6
Make example for this keyboard (after setting up your build environment):
make cannonkeys/Satisfaction75:default
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).

View File

@ -0,0 +1,57 @@
# project specific files
# SRC = ssd1306.c
## chip/board settings
# the next two should match the directories in
# <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
MCU_FAMILY = STM32
MCU_SERIES = STM32F0xx
# linker script to use
# it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
# or <this_dir>/ld/
MCU_LDSCRIPT = STM32F072xB
# startup code to use
# is should exist in <chibios>/os/common/ports/ARMCMx/compilers/GCC/mk/
MCU_STARTUP = stm32f0xx
# it should exist either in <chibios>/os/hal/boards/
# or <this_dir>/boards
BOARD = ST_STM32F072B_DISCOVERY
# Cortex version
# Teensy LC is cortex-m0; Teensy 3.x are cortex-m4
MCU = cortex-m0
# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
ARMV = 6
# If you want to be able to jump to bootloader from firmware on STM32 MCUs,
# set the correct BOOTLOADER_ADDRESS. Either set it here, or define it in
# ./bootloader_defs.h or in ./boards/<FOO>/bootloader_defs.h (if you have
# a custom board definition that you plan to reuse).
# If you're not setting it here, leave it commented out.
# It is chip dependent, the correct number can be looked up here (page 175):
# http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf
# This also requires a patch to chibios:
# <tmk_dir>/tmk_core/tool/chibios/ch-bootloader-jump.patch
#STM32_BOOTLOADER_ADDRESS = 0x1FFFC800
# Build Options
# comment out to disable the options.
#
SRC += led.c \
satisfaction_encoder.c \
satisfaction_oled.c
#BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration
MOUSEKEY_ENABLE = yes # Mouse keys
EXTRAKEY_ENABLE = yes # Audio control and System control
CONSOLE_ENABLE = yes # Console for debug
COMMAND_ENABLE = yes # Commands for debug and configuration
SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend
NKRO_ENABLE = yes # USB Nkey Rollover
CUSTOM_MATRIX = no # Custom matrix file
ENCODER_ENABLE = yes
QWIIC_ENABLE += MICRO_OLED
#BACKLIGHT_ENABLE = yes
# RAW_ENABLE = yes
# DYNAMIC_KEYMAP_ENABLE = yes
DEFAULT_FOLDER = cannonkeys/satisfaction75

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,118 @@
#pragma once
#include "quantum.h"
// The first section contains all of the arguements
// The second converts the arguments into a two-dimensional array
#define LAYOUT_default( \
K000, K002, K003, K004, K005, K006, K007, K008, K009, K010, K011, K012, K013, \
K100, K101, K102, K103, K104, K105, K106, K107, K108, K109, K110, K111, K112, K113, K115, \
K200, K201, K202, K203, K204, K205, K206, K207, K208, K209, K210, K211, K212, K213, K215, \
K300, K301, K302, K303, K304, K305, K306, K307, K308, K309, K310, K311, K312, K315, \
K400, K401, K402, K403, K404, K405, K406, K407, K408, K409, K410, K411, K413, K415, \
K500, K501, K502, K505, K509, K510, K511, K512, K513, K515 \
) { \
{ K000, KC_NO, K002, K003, K004, K005, K006, K007, K008, K009, K010, K011, K012, K013, KC_NO, KC_NO }, \
{ K100, K101, K102, K103, K104, K105, K106, K107, K108, K109, K110, K111, K112, K113, KC_NO, K115 }, \
{ K200, K201, K202, K203, K204, K205, K206, K207, K208, K209, K210, K211, K212, K213, KC_NO, K215 }, \
{ K300, K301, K302, K303, K304, K305, K306, K307, K308, K309, K310, K311, K312, KC_NO, KC_NO, K315 }, \
{ K400, K401, K402, K403, K404, K405, K406, K407, K408, K409, K410, K411, KC_NO, K413, KC_NO, K415 }, \
{ K500, K501, K502, KC_NO, KC_NO, K505, KC_NO, KC_NO, KC_NO, K509, K510, K511, K512, K513, KC_NO, K515 } \
}
/* screen off after this many milliseconds */
#define ScreenOffInterval 60000 /* milliseconds */
typedef union {
uint8_t raw;
struct {
bool enable :1;
bool breathing : 1;
uint8_t level :6;
};
} backlight_config_t;
// Start these at the USER code range in VIA
enum my_keycodes {
ENC_PRESS = 0x5F80,
CLOCK_SET,
OLED_TOGG
};
enum encoder_modes {
ENC_MODE_VOLUME,
ENC_MODE_MEDIA,
ENC_MODE_SCROLL,
ENC_MODE_BRIGHTNESS,
ENC_MODE_BACKLIGHT,
ENC_MODE_CUSTOM0,
ENC_MODE_CUSTOM1,
ENC_MODE_CUSTOM2,
_NUM_ENCODER_MODES,
ENC_MODE_CLOCK_SET // This shouldn't be included in the default modes, so we put it after NUM_ENCODER_MODES
};
enum oled_modes {
OLED_DEFAULT,
OLED_TIME,
OLED_OFF,
_NUM_OLED_MODES
};
// Keyboard Information
extern volatile uint8_t led_numlock;
extern volatile uint8_t led_capslock;
extern volatile uint8_t led_scrolllock;
extern uint8_t layer;
// OLED Behavior
extern uint16_t last_flush;
extern bool queue_for_send;
extern uint8_t oled_mode;
extern bool oled_sleeping;
// Encoder Behavior
extern uint8_t encoder_value;
extern uint8_t encoder_mode;
extern uint8_t enabled_encoder_modes;
// RTC
extern RTCDateTime last_timespec;
extern uint16_t last_minute;
// RTC Configuration
extern bool clock_set_mode;
extern uint8_t time_config_idx;
extern int8_t hour_config;
extern int16_t minute_config;
extern int8_t year_config;
extern int8_t month_config;
extern int8_t day_config;
extern uint8_t previous_encoder_mode;
// Backlighting
extern backlight_config_t kb_backlight_config;
extern bool kb_backlight_breathing;
void pre_encoder_mode_change(void);
void post_encoder_mode_change(void);
void change_encoder_mode(bool negative);
uint16_t handle_encoder_clockwise(void);
uint16_t handle_encoder_ccw(void);
uint16_t handle_encoder_press(void);
void update_time_config(int8_t increment);
__attribute__ ((weak))
void draw_ui(void);
void draw_default(void);
void draw_clock(void);
void backlight_init_ports(void);
void backlight_set(uint8_t level);
bool is_breathing(void);
void breathing_enable(void);
void breathing_disable(void);
// void backlight_save_to_eeprom(uint8_t level);
// uint8_t backlight_config_load();

View File

@ -0,0 +1,174 @@
#include "satisfaction75.h"
void pre_encoder_mode_change(){
if(encoder_mode == ENC_MODE_CLOCK_SET){
RTCDateTime timespec;
timespec.year = year_config;
timespec.month = month_config;
timespec.day = day_config;
// timespec.dayofweek = last_timespec.dayofweek;
// timespec.dstflag = last_timespec.dstflag;
timespec.millisecond = (hour_config * 60 + minute_config) * 60 * 1000;
rtcSetTime(&RTCD1, &timespec);
}
}
void post_encoder_mode_change(){
if(encoder_mode == ENC_MODE_CLOCK_SET){
hour_config = (last_minute / 60);
minute_config = last_minute % 60;
year_config = last_timespec.year;
month_config = last_timespec.month;
day_config = last_timespec.day;
time_config_idx = 0;
}
}
void change_encoder_mode(bool negative){
pre_encoder_mode_change();
do {
if(negative){
if (encoder_mode == 0){
encoder_mode = _NUM_ENCODER_MODES - 1;
} else{
encoder_mode = encoder_mode - 1;
}
} else {
encoder_mode = (encoder_mode + 1) % _NUM_ENCODER_MODES;
}
} while(((1 << encoder_mode) & enabled_encoder_modes) == 0);
post_encoder_mode_change();
}
void update_time_config(int8_t increment){
uint8_t day_limit = 31;
uint16_t adjusted_year = 1980 + year_config;
switch(time_config_idx){
case 0: // hour
default:
hour_config = (hour_config + increment) % 24;
if (hour_config < 0){
hour_config += 24;
}
break;
case 1: // minute
minute_config = (minute_config + increment) % 60;
if (minute_config < 0){
minute_config += 60;
}
break;
case 2: // year
year_config += increment;
break;
case 3: // month
month_config = (month_config % 12) + increment;
if (month_config <= 0){
month_config += 12;
}
break;
case 4: //day
if (month_config == 9 || month_config == 4 || month_config == 6 || month_config == 11){
day_limit = 30;
} else if(month_config == 2){
day_limit = adjusted_year % 4 == 0 && !(adjusted_year % 100 == 0 && adjusted_year % 400 != 0) ? 29 : 28;
}
day_config = (day_config % day_limit) + increment;
if(day_config <= 0){
day_config += day_limit;
}
break;
}
}
uint16_t handle_encoder_clockwise(){
uint16_t mapped_code = 0;
switch(encoder_mode){
default:
case ENC_MODE_VOLUME:
mapped_code = KC_VOLU;
break;
case ENC_MODE_MEDIA:
mapped_code = KC_MEDIA_NEXT_TRACK;
break;
case ENC_MODE_SCROLL:
mapped_code = KC_WH_D;
break;
case ENC_MODE_BACKLIGHT:
// mapped_code = BL_INC;
kb_backlight_config.level = kb_backlight_config.level + 1;
if(kb_backlight_config.level > BACKLIGHT_LEVELS){
kb_backlight_config.level = BACKLIGHT_LEVELS;
}
backlight_set(kb_backlight_config.level);
break;
case ENC_MODE_BRIGHTNESS:
mapped_code = KC_BRIGHTNESS_UP;
break;
case ENC_MODE_CLOCK_SET:
update_time_config(1);
queue_for_send = true;
break;
}
return mapped_code;
}
uint16_t handle_encoder_ccw(){
uint16_t mapped_code = 0;
switch(encoder_mode){
default:
case ENC_MODE_VOLUME:
mapped_code = KC_VOLD;
break;
case ENC_MODE_MEDIA:
mapped_code = KC_MEDIA_PREV_TRACK;
break;
case ENC_MODE_SCROLL:
mapped_code = KC_WH_U;
break;
case ENC_MODE_BACKLIGHT:
// mapped_code = BL_DEC;
if(kb_backlight_config.level != 0){
kb_backlight_config.level = kb_backlight_config.level - 1;
}
backlight_set(kb_backlight_config.level);
break;
case ENC_MODE_BRIGHTNESS:
mapped_code = KC_BRIGHTNESS_DOWN;
break;
case ENC_MODE_CLOCK_SET:
update_time_config(-1);
queue_for_send = true;
break;
}
return mapped_code;
}
uint16_t handle_encoder_press(){
uint16_t mapped_code = 0;
switch(encoder_mode){
case ENC_MODE_VOLUME:
mapped_code = KC_MUTE;
break;
case ENC_MODE_MEDIA:
mapped_code = KC_MEDIA_PLAY_PAUSE;
break;
case ENC_MODE_SCROLL:
mapped_code = KC_BTN3;
break;
case ENC_MODE_BACKLIGHT:
// mapped_code = BL_TOGG;
kb_backlight_config.breathing = !kb_backlight_config.breathing;
if(!kb_backlight_config.breathing){
breathing_disable();
} else{
breathing_enable();
}
break;
case ENC_MODE_CLOCK_SET:
time_config_idx = (time_config_idx + 1) % 5;
default:
case ENC_MODE_BRIGHTNESS:
break;
}
return mapped_code;
}

View File

@ -0,0 +1,269 @@
#include "satisfaction75.h"
#include "micro_oled.h"
__attribute__ ((weak))
void draw_ui() {
clear_buffer();
last_flush = timer_read();
send_command(DISPLAYON);
if(clock_set_mode){
draw_clock();
return;
}
switch (oled_mode){
default:
case OLED_DEFAULT:
draw_default();
break;
case OLED_TIME:
draw_clock();
break;
case OLED_OFF:
send_command(DISPLAYOFF);
break;
}
}
void draw_encoder(int8_t startX, int8_t startY, bool show_legend){
if(show_legend){
draw_string(startX + 1, startY + 2, "ENC", PIXEL_ON, NORM, 0);
} else {
startX -= 22;
}
draw_rect_filled_soft(startX + 22, startY + 1, 3 + (3 * 6), 9, PIXEL_ON, NORM);
char* mode_string = "";
switch(encoder_mode){
default:
case ENC_MODE_VOLUME:
mode_string = "VOL";
break;
case ENC_MODE_MEDIA:
mode_string = "MED";
break;
case ENC_MODE_SCROLL:
mode_string = "SCR";
break;
case ENC_MODE_BRIGHTNESS:
mode_string = "BRT";
break;
case ENC_MODE_BACKLIGHT:
mode_string = "BKL";
break;
case ENC_MODE_CLOCK_SET:
mode_string = "CLK";
break;
case ENC_MODE_CUSTOM0:
mode_string = "CS0";
break;
case ENC_MODE_CUSTOM1:
mode_string = "CS1";
break;
case ENC_MODE_CUSTOM2:
mode_string = "CS2";
break;
}
draw_string(startX + 24, startY + 2, mode_string, PIXEL_ON, XOR, 0);
}
void draw_layer_section(int8_t startX, int8_t startY, bool show_legend){
if(show_legend){
draw_string(startX + 1, startY + 2, "LAYER", PIXEL_ON, NORM, 0);
} else {
startX -= 32;
}
draw_rect_filled_soft(startX + 32, startY + 1, 9, 9, PIXEL_ON, NORM);
draw_char(startX + 34, startY + 2, layer + 0x30, PIXEL_ON, XOR, 0);
}
void draw_default(){
uint8_t hour = last_minute / 60;
uint16_t minute = last_minute % 60;
if(encoder_mode == ENC_MODE_CLOCK_SET){
hour = hour_config;
minute = minute_config;
}
bool is_pm = (hour / 12) > 0;
hour = hour % 12;
if (hour == 0){
hour = 12;
}
char hour_str[2] = "";
char min_str[2] = "";
sprintf(hour_str, "%02d", hour);
sprintf(min_str, "%02d", minute);
uint8_t mods = get_mods();
/* Layer indicator is 41 x 10 pixels */
draw_layer_section(0,0,true);
#define ENCODER_INDICATOR_X 45
#define ENCODER_INDICATOR_Y 0
draw_encoder(ENCODER_INDICATOR_X, ENCODER_INDICATOR_Y, true);
/* Matrix display is 19 x 9 pixels */
#define MATRIX_DISPLAY_X 0
#define MATRIX_DISPLAY_Y 18
for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
for (uint8_t y = 0; y < MATRIX_COLS; y++) {
draw_pixel(MATRIX_DISPLAY_X + y + 2, MATRIX_DISPLAY_Y + x + 2,(matrix_get_row(x) & (1 << y)) > 0, NORM);
}
}
draw_rect_soft(MATRIX_DISPLAY_X, MATRIX_DISPLAY_Y, 19, 9, PIXEL_ON, NORM);
/* hadron oled location on thumbnail */
draw_rect_filled_soft(MATRIX_DISPLAY_X + 14, MATRIX_DISPLAY_Y + 2, 3, 1, PIXEL_ON, NORM);
/* Mod display is 41 x 16 pixels */
#define MOD_DISPLAY_X 30
#define MOD_DISPLAY_Y 18
if (mods & MOD_LSFT) {
draw_rect_filled_soft(MOD_DISPLAY_X + 0, MOD_DISPLAY_Y, 5 + (1 * 6), 11, PIXEL_ON, NORM);
draw_string(MOD_DISPLAY_X + 3, MOD_DISPLAY_Y + 2, "S", PIXEL_OFF, NORM, 0);
} else {
draw_string(MOD_DISPLAY_X + 3, MOD_DISPLAY_Y + 2, "S", PIXEL_ON, NORM, 0);
}
if (mods & MOD_LCTL) {
draw_rect_filled_soft(MOD_DISPLAY_X + 10, MOD_DISPLAY_Y, 5 + (1 * 6), 11, PIXEL_ON, NORM);
draw_string(MOD_DISPLAY_X + 13, MOD_DISPLAY_Y + 2, "C", PIXEL_OFF, NORM, 0);
} else {
draw_string(MOD_DISPLAY_X + 13, MOD_DISPLAY_Y + 2, "C", PIXEL_ON, NORM, 0);
}
if (mods & MOD_LALT) {
draw_rect_filled_soft(MOD_DISPLAY_X + 20, MOD_DISPLAY_Y, 5 + (1 * 6), 11, PIXEL_ON, NORM);
draw_string(MOD_DISPLAY_X + 23, MOD_DISPLAY_Y + 2, "A", PIXEL_OFF, NORM, 0);
} else {
draw_string(MOD_DISPLAY_X + 23, MOD_DISPLAY_Y + 2, "A", PIXEL_ON, NORM, 0);
}
if (mods & MOD_LGUI) {
draw_rect_filled_soft(MOD_DISPLAY_X + 30, MOD_DISPLAY_Y, 5 + (1 * 6), 11, PIXEL_ON, NORM);
draw_string(MOD_DISPLAY_X + 33, MOD_DISPLAY_Y + 2, "G", PIXEL_OFF, NORM, 0);
} else {
draw_string(MOD_DISPLAY_X + 33, MOD_DISPLAY_Y + 2, "G", PIXEL_ON, NORM, 0);
}
/* Lock display is 23 x 21 */
#define LOCK_DISPLAY_X 100
#define LOCK_DISPLAY_Y 0
if (led_capslock == true) {
draw_rect_filled_soft(LOCK_DISPLAY_X + 0, LOCK_DISPLAY_Y, 5 + (3 * 6), 9, PIXEL_ON, NORM);
draw_string(LOCK_DISPLAY_X + 3, LOCK_DISPLAY_Y +1, "CAP", PIXEL_OFF, NORM, 0);
} else if (led_capslock == false) {
draw_string(LOCK_DISPLAY_X + 3, LOCK_DISPLAY_Y +1, "CAP", PIXEL_ON, NORM, 0);
}
if (led_scrolllock == true) {
draw_rect_filled_soft(LOCK_DISPLAY_X + 0, LOCK_DISPLAY_Y + 11, 5 + (3 * 6), 9, PIXEL_ON, NORM);
draw_string(LOCK_DISPLAY_X + 3, LOCK_DISPLAY_Y + 11 +1, "SCR", PIXEL_OFF, NORM, 0);
} else if (led_scrolllock == false) {
draw_string(LOCK_DISPLAY_X + 3, LOCK_DISPLAY_Y + 11 +1, "SCR", PIXEL_ON, NORM, 0);
}
#define TIME_DISPLAY_X 82
#define TIME_DISPLAY_Y 22
draw_string(TIME_DISPLAY_X, TIME_DISPLAY_Y, hour_str, PIXEL_ON, NORM, 0);
draw_string(TIME_DISPLAY_X + 11, TIME_DISPLAY_Y, ":", PIXEL_ON, NORM, 0);
draw_string(TIME_DISPLAY_X + 15, TIME_DISPLAY_Y, min_str, PIXEL_ON, NORM, 0);
if(is_pm){
draw_string(TIME_DISPLAY_X + 27, TIME_DISPLAY_Y, "pm", PIXEL_ON, NORM, 0);
} else{
draw_string(TIME_DISPLAY_X + 27, TIME_DISPLAY_Y, "am", PIXEL_ON, NORM, 0);
}
send_buffer();
}
void draw_clock(){
int8_t hour = last_minute / 60;
int16_t minute = last_minute % 60;
int16_t year = last_timespec.year + 1980;
int8_t month = last_timespec.month;
int8_t day = last_timespec.day;
if(encoder_mode == ENC_MODE_CLOCK_SET){
hour = hour_config;
minute = minute_config;
year = year_config + 1980;
month = month_config;
day = day_config;
}
bool is_pm = (hour / 12) > 0;
hour = hour % 12;
if (hour == 0){
hour = 12;
}
char hour_str[2] = "";
char min_str[2] = "";
char year_str[4] = "";
char month_str[2] = "";
char day_str[2] = "";
sprintf(hour_str, "%02d", hour);
sprintf(min_str, "%02d", minute);
sprintf(year_str, "%d", year);
sprintf(month_str, "%02d", month);
sprintf(day_str, "%02d", day);
#define DATE_DISPLAY_X 6
#define DATE_DISPLAY_Y 0
draw_string(DATE_DISPLAY_X, DATE_DISPLAY_Y, year_str, PIXEL_ON, NORM, 0);
draw_string(DATE_DISPLAY_X + 25, DATE_DISPLAY_Y, "-", PIXEL_ON, NORM, 0);
draw_string(DATE_DISPLAY_X + 31, DATE_DISPLAY_Y, month_str, PIXEL_ON, NORM, 0);
draw_string(DATE_DISPLAY_X + 44, DATE_DISPLAY_Y, "-", PIXEL_ON, NORM, 0);
draw_string(DATE_DISPLAY_X + 50, DATE_DISPLAY_Y, day_str, PIXEL_ON, NORM, 0);
#define CLOCK_DISPLAY_X 6
#define CLOCK_DISPLAY_Y 14
draw_string(CLOCK_DISPLAY_X, CLOCK_DISPLAY_Y, hour_str, PIXEL_ON, NORM, 1);
draw_string(CLOCK_DISPLAY_X + 17, CLOCK_DISPLAY_Y, ":", PIXEL_ON, NORM, 1);
draw_string(CLOCK_DISPLAY_X + 25, CLOCK_DISPLAY_Y, min_str, PIXEL_ON, NORM, 1);
if(is_pm){
draw_string(CLOCK_DISPLAY_X + 41, CLOCK_DISPLAY_Y, "pm", PIXEL_ON, NORM, 1);
} else{
draw_string(CLOCK_DISPLAY_X + 41, CLOCK_DISPLAY_Y, "am", PIXEL_ON, NORM, 1);
}
if(clock_set_mode){
switch(time_config_idx){
case 0: // hour
default:
draw_line(CLOCK_DISPLAY_X, CLOCK_DISPLAY_Y + 17, CLOCK_DISPLAY_X + 16, CLOCK_DISPLAY_Y + 17, PIXEL_ON, NORM);
break;
case 1: // minute
draw_line(CLOCK_DISPLAY_X + 25, CLOCK_DISPLAY_Y + 17, CLOCK_DISPLAY_X + 41, CLOCK_DISPLAY_Y + 17, PIXEL_ON, NORM);
break;
case 2: // year
draw_line(DATE_DISPLAY_X, DATE_DISPLAY_Y + 9, DATE_DISPLAY_X + 23, DATE_DISPLAY_Y + 9, PIXEL_ON, NORM);
break;
case 3: // month
draw_line(DATE_DISPLAY_X + 31, DATE_DISPLAY_Y + 9, DATE_DISPLAY_X + 43, DATE_DISPLAY_Y + 9, PIXEL_ON, NORM);
break;
case 4: //day
draw_line(DATE_DISPLAY_X + 50, DATE_DISPLAY_Y + 9, DATE_DISPLAY_X + 61, DATE_DISPLAY_Y + 9,PIXEL_ON, NORM);
break;
}
}
draw_encoder(80, 0, true);
draw_layer_section(80, 11, true);
#define CAPS_DISPLAY_X 86
#define CAPS_DISPLAY_Y 22
if (led_capslock == true) {
draw_rect_filled_soft(CAPS_DISPLAY_X, CAPS_DISPLAY_Y, 5 + (4 * 6), 9, PIXEL_ON, NORM);
draw_string(CAPS_DISPLAY_X + 3, CAPS_DISPLAY_Y +1, "CAPS", PIXEL_OFF, NORM, 0);
} else if (led_capslock == false) {
draw_string(CAPS_DISPLAY_X + 3, CAPS_DISPLAY_Y +1, "CAPS", PIXEL_ON, NORM, 0);
}
send_buffer();
}

View File

@ -0,0 +1,7 @@
/* Address for jumping to bootloader on STM32 chips. */
/* It is chip dependent, the correct number can be looked up here (page 175):
* http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf
* This also requires a patch to chibios:
* <tmk_dir>/tmk_core/tool/chibios/ch-bootloader-jump.patch
*/
#define STM32_BOOTLOADER_ADDRESS 0x1FFFC800

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
#include "ck4x4.h"

View File

@ -0,0 +1,15 @@
#pragma once
#include "quantum.h"
#define LAYOUT( \
k00, k01, k02, k03, \
k10, k11, k12, k13, \
k20, k21, k22, k23, \
k30, k31, k32, k33 \
) {\
{ k00, k01, k02, k03 }, \
{ k10, k11, k12, k13 }, \
{ k20, k21, k22, k23 }, \
{ k30, k31, k32, k33 }, \
}

View File

@ -0,0 +1,70 @@
/*
Copyright 2015 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/>.
*/
#pragma once
/* USB Device descriptor parameter */
#define VENDOR_ID 0xFEED
#define PRODUCT_ID 0x6464
#define DEVICE_VER 0x0001
/* in python2: list(u"whatever".encode('utf-16-le')) */
/* at most 32 characters or the ugly hack in usb_main.c borks */
#define MANUFACTURER QMK
#define PRODUCT CK4x4
#define DESCRIPTION Cannon Keys 4x4 MacroPad
/* key matrix size */
#define MATRIX_ROWS 4
#define MATRIX_COLS 4
#define MATRIX_COL_PINS { B7, B8, B9, B10 }
#define MATRIX_ROW_PINS { B3, B4, B5, B6 }
#define DIODE_DIRECTION COL2ROW
//LEDS A6, RGB B15
/* define if matrix has ghost */
//#define MATRIX_HAS_GHOST
/* Set 0 if debouncing isn't needed */
#define DEBOUNCE 5
/* 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
/*
* 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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,29 @@
/*
Copyright 2012,2013 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/>.
*/
#include QMK_KEYBOARD_H
const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT(KC_7, KC_8, KC_9, KC_MINUS, \
KC_4, KC_5, KC_6, KC_PLUS, \
KC_1, KC_2, KC_3, KC_ENTER, \
RESET, KC_NO, KC_NO, KC_NO \
), // test with KC_CAPS, KC_A, RESET
};
const uint16_t fn_actions[] = {
};

Some files were not shown because too many files have changed in this diff Show More