# Conflicts: # tmk_core/common/keyboard.cpull/3720/head
@ -0,0 +1,5 @@ | |||
--- | |||
name: Blank issue | |||
about: If you're 100% sure that you don't need one of the other issue templates, use this one instead. | |||
--- |
@ -0,0 +1,31 @@ | |||
--- | |||
name: Bug report | |||
about: Create a report to help us improve the QMK Firmware | |||
--- | |||
<!-- Provide a general summary of the bug in the Title above --> | |||
<!-- This template is entirely option and can be removed, but is here to help both you and us. --> | |||
<!-- This text and anything on lines wrapped like this one will not show up in the final text. This text is to help us and you. --> | |||
**Describe the bug** | |||
<!-- A clear and concise description of what the bug is. --> | |||
**System Information** | |||
- Keyboard: | |||
- Revision (if applicable): | |||
- Operating System: | |||
- avr-gcc version: | |||
<!-- Run `avr-gcc --version` to find out --> | |||
- arm gcc version: | |||
<!-- Run `arm-none-eabi-gcc --version` to find out --> | |||
- QMK Firmware version: | |||
<!-- You can run `git describe --abbrev=0 --tags` to find this out --> | |||
- Any keyboard related software installed? | |||
- [ ] Auto Hot Key | |||
- [ ] Karabiner | |||
- [ ] Other | |||
**Additional context** | |||
<!-- Add any other context about the problem here. --> |
@ -0,0 +1,19 @@ | |||
--- | |||
name: Feature request | |||
about: Suggest a new feature or changes to existing features | |||
--- | |||
<!--- Provide a general summary of the changes you want in the Title above --> | |||
<!-- This template is entirely option and can be removed, but is here to help both you and us. --> | |||
<!-- This text and anything on lines wrapped like this one will not show up in the final text. This text is to help us and you. --> | |||
## Feature Request Type | |||
- [ ] Core Functionality | |||
- [ ] Add-on hardware support (e.g. audio, RGB, OLED screen, etc.) | |||
- [ ] Alteration (enhancement/optimization) of existing Feature(s) | |||
- [ ] New behavior | |||
## Description | |||
<!-- A few sentences describing what it is that you'd like to see. Additional information (such as links to spec sheets, licensing info, other related issues or PR's, etc) would be helpful. --> |
@ -0,0 +1,9 @@ | |||
--- | |||
name: Other issues | |||
about: Anything else that doesn't fall into the above categories. | |||
--- | |||
<!--- Provide a general summary of the changes you want in the Title above --> | |||
<!-- This text and anything on lines wrapped like this one will not show up in the final text. This text is to help us and you. --> | |||
<!-- Please check https://docs.qmk.fm/#/support for additional resources first. If that doesn't answer your question, check the bug report option, as that may be more appropriate. --> |
@ -0,0 +1,32 @@ | |||
<!--- Provide a general summary of your changes in the Title above --> | |||
<!--- This template is entirely option and can be removed, but is here to help both you and us. --> | |||
<!--- This text and anything on lines wrapped like this one will not show up in the final text. This text is to help us and you. --> | |||
## Description | |||
<!--- Describe your changes in detail --> | |||
## Types of changes | |||
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: --> | |||
- [ ] Core | |||
- [ ] Bugfix | |||
- [ ] New Feature | |||
- [ ] Enhancement/Optimization | |||
- [ ] Keyboard (addition or update) | |||
- [ ] Keymap/Layout/Userspace (addition or update) | |||
- [ ] Documentation | |||
## Issues Fixed or Closed by this PR | |||
* | |||
## Checklist: | |||
<!--- Go over all the following points, and put an `x` in all the boxes that apply. --> | |||
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> | |||
- [ ] My code follows the code style of this project. | |||
- [ ] My change requires a change to the documentation. | |||
- [ ] I have updated the documentation accordingly. | |||
- [ ] I have read the **CONTRIBUTING** document. (https://docs.qmk.fm/#/contributing) | |||
- [ ] I have added tests to cover my changes. | |||
- [ ] I have tested the changes and verified that they work and don't break anything (as well as I can manage). |
@ -1,28 +1,29 @@ | |||
FROM debian:jessie | |||
MAINTAINER Erik Dasque <erik@frenchguys.com> | |||
FROM debian | |||
RUN apt-get update && apt-get install --no-install-recommends -y build-essential \ | |||
gcc \ | |||
unzip \ | |||
wget \ | |||
zip \ | |||
gcc-avr \ | |||
binutils-avr \ | |||
RUN apt-get update && apt-get install --no-install-recommends -y \ | |||
avr-libc \ | |||
avrdude \ | |||
binutils-arm-none-eabi \ | |||
binutils-avr \ | |||
build-essential \ | |||
dfu-programmer \ | |||
dfu-util \ | |||
gcc \ | |||
gcc-arm-none-eabi \ | |||
binutils-arm-none-eabi \ | |||
libnewlib-arm-none-eabi \ | |||
gcc-avr \ | |||
git \ | |||
libnewlib-arm-none-eabi \ | |||
software-properties-common \ | |||
avrdude \ | |||
unzip \ | |||
wget \ | |||
zip \ | |||
&& rm -rf /var/lib/apt/lists/* | |||
ENV keyboard=ergodox | |||
ENV subproject=ez | |||
ENV keymap=default | |||
ENV KEYBOARD=ergodox_ez | |||
ENV KEYMAP=default | |||
VOLUME /qmk_firmware | |||
WORKDIR /qmk_firmware | |||
COPY . . | |||
VOLUME /qmk | |||
WORKDIR /qmk | |||
CMD make clean ; make keyboard=${keyboard} subproject=${subproject} keymap=${keymap} | |||
CMD make $KEYBOARD:$KEYMAP |
@ -0,0 +1,4 @@ | |||
# Languages | |||
* [English](/) | |||
* [Chinese](zh/) |
@ -0,0 +1,87 @@ | |||
# ARM Debugging usign Eclipse | |||
This page describes how to setup debugging for ARM MCUs using an SWD adapter and open-source/free tools. In this guide we will install GNU MCU Eclipse IDE for C/C++ Developers and OpenOCD together with all the necessary dependencies. | |||
This guide is catered towards advance users and assumes you can compile an ARM compatible keyboard on your machine using the MAKE flow. | |||
## Installing the software | |||
The main objective here is to get the MCU Eclipse IDE correcly installed on our machine. The necesarry instructions are derived from [this](https://gnu-mcu-eclipse.github.io/install/) install guide. | |||
### The xPack Manager | |||
This tool is a software package manager and it is used to help us get the necesarry depencencies. | |||
XPM runs using Node.js so grab that form [here](https://nodejs.org/en/). After installation, open a terminal and type `npm -v`. A reply with the version number means that the instalation was successful. | |||
XPM instalation instructions can be found [here](https://www.npmjs.com/package/xpm) and are OS specific. Entering `xpm --version` to your terminal should return the software version. | |||
### The ARM Toolchain | |||
Using XPM it is very easy to install the ARM toolchain. Enter the command `xpm install --global @gnu-mcu-eclipse/arm-none-eabi-gcc`. | |||
### Windows build tools | |||
If you are using windows you need to install this! | |||
`xpm install --global @gnu-mcu-eclipse/windows-build-tools` | |||
### Programer/Debugger Drivers | |||
Now its the time to install your programer's drivers. This tutorial was made using an ST-Link v2 which you can get from almost anywhere. | |||
If you have an ST-Link the drivers can be found [here](https://www.st.com/en/development-tools/stsw-link009.html) otherwise consult the manufuturer of your tool. | |||
### OpenOCD | |||
This dependency allows SWD access from GDB and it is essential for debugging. Run `xpm install --global @gnu-mcu-eclipse/openocd`. | |||
### Java | |||
Java is needed by Eclipse so please download it from [here](https://www.oracle.com/technetwork/java/javase/downloads/index.html). | |||
### GNU MCU Eclipse IDE | |||
Now its finally time to install the IDE. Use the Release page [here](https://github.com/gnu-mcu-eclipse/org.eclipse.epp.packages/releases/) to get the latest version. | |||
## Configuring Eclipse | |||
Open up the Eclipse IDE we just downloaded. To import our QMK directory select File -> Import -> C/C++ -> Existing code as Makefile Project. Select next and use Browse to select your QMK folder. In the tool-chain list select ARM Cross GCC and select Finish. | |||
Now you can see the QMK folder on the left hand side. Right click it and select Properties. On the left hand side, expand MCU and select ARM Toolchain Paths. Press xPack and OK. Repeat for OpenOCD Path and if you are on windows for Build Tool Path. Select Apply and Close. | |||
Now its time to install the necessary MCU packages. Go to Packs perspective by selecting Window -> Open Perspective -> Others -> Packs. Now select the yellow refresh symbol next to the Packs tab. This will take a long time as it is requesting the MCU definitions from various places. If some of the links fail you can probably select Ignore. | |||
When this finishes you must find the MCU which we will be building/debugging for. In this example I will be using the STM32F3 series MCUs. On the left, select STMicroelectonics -> STM32F3 Series. On the middle window we can see the pack. Right click and select Install. Once that is done we can go back to the default perspective, Window -> Open Perspective -> Others -> C/C++. | |||
We need to let eclipse know the device we intent to build QMK on. Right click on the QMK folder -> Properties -> C/C++ Build -> Settings. Select the Devices tab and under devices select the appropriate variant of your MCU. For my example it is STM32F303CC | |||
While we are here let's setup the build command as well. Select C/C++ Build and then the Behavior tab. On the build command, replace `all` with your necessary make command. For example for a rev6 Planck with the default keymap this would be `planck/rev6:default`. Select Apply and Close. | |||
## Building | |||
If you have setup everything correctly pressing the hammer button should build the firmware for you and a .bin file should appear. | |||
## Debugging | |||
### Connecting the Debugger | |||
ARM MCUs use the Single Wire Debug (SWD) protocol which comprises of the clock (SWCLK) signal and the data (SWDIO) signal. Connecting this two wires and ground should be enough to allow full manipulation of the MCU. Here we assume that the keyboard will be powered though USB. The RESET signal is not necessary as we can manually assert it using the reset button. For a more advance setup, the SWO signal can be used which pipes printf and scanf asynchronously to the host but for our setup we will ignore it. | |||
NOTE: Make sure the SWCLK and SWDIO pins are not used in the matrix of your keyboard. If they are you can temporarily switch them for some other pins. | |||
### Configuring the Debugger | |||
Right click on your QMK folder, select Debug As -> Debug Configuration. Here double click on GDB OpenOCD Debugging. Select the debugger tab and enter the configuration necessary for your MCU. This might take some fiddling and googleing to find out. The default script for the STM32F3 is called stm32f3discovery.cfg. To let OpenOCD know, in the Config options enter `-f board/stm32f3discovery.cfg`. | |||
NOTE: In my case this configuration script requires editing to disable the reset assertion. The locations of the scripts can be found in the actual executable field usually under the path `openocd/version/.content/scripts/board`. Here I edited `reset_config srst_only` to `reset_config none`. | |||
Select Apply and Close. | |||
### Running the Debugger. | |||
Reset your keyboard. | |||
Press the bug icon and if all goes well you should soon find yourself in the debug perspective. Here the program counter will pause at the beginning of the main function and way for you to press Play. Most of the features of all debuggers work on ARM MCUs but for exact details google is your friend! | |||
Happy debugging! |
@ -1,7 +1,9 @@ | |||
A QMK collaborator is a keyboard maker/designer that is interested in helping QMK grow and fully support their keyboard(s), and encouraging their users/customers to submit features, ideas, and keymaps. We're always looking to add more keyboards and collaborators, but we ask that they fulfill these requirements: | |||
# Becoming a QMK Collaborator | |||
* **Have a PCB available for sale** - unfortunately there's just too much variation and complications with handwired keyboards. | |||
* **Maintain the your keyboard's directory** - this may just require an initial setup to get your keyboard working, but it could also include accommodating changes made to QMK's core. | |||
* **Approve and merge your keyboard's keymap pull requests** - we like to encourage users to contribute their keymaps for others to see and work from when creating their own. | |||
A QMK collaborator is a keyboard maker or designer that is interested in helping QMK grow and fully support their keyboard(s), and encouraging their users and customers to submit features, ideas, and keymaps. We're always looking to add more keyboards and collaborators, but we ask that they fulfill these requirements: | |||
* **Have a PCB available for sale.** Unfortunately there's just too much variation and complications with handwired keyboards. | |||
* **Maintain your keyboard in QMK.** This may just require an initial setup to get your keyboard working, but it could also include accommodating changes made to QMK's core that might break or render any custom code redundant. | |||
* **Approve and merge keymap pull requests for your keyboard.** We like to encourage users to contribute their keymaps for others to see and work from when creating their own. | |||
If you feel you meet these requirements, shoot us an email at hello@qmk.fm with an introduction and some links to your keyboard! |
@ -0,0 +1,89 @@ | |||
# Combos | |||
The Combo feature is a chording type solution for adding custom actions. It lets you hit multiple keys at once and produce a different effect. For instance, hitting `A` and `S` within the tapping term would hit `ESC` instead, or have it perform even more complex tasks. | |||
To enable this feature, yu need to add `COMBO_ENABLE = yes` to your `rules.mk`. | |||
Additionally, in your `config.h`, you'll need to specify the number of combos that you'll be using, by adding `#define COMBO_COUNT 1` (replacing 1 with the number that you're using). | |||
<!-- At this time, this is necessary --> | |||
Also, by default, the tapping term for the Combos is set to the same value as `TAPPING_TERM` (200 by default on most boards). But you can specify a different value by defining it in your `config.h`. For instance: `#define COMBO_TERM 300` would set the time out period for combos to 300ms. | |||
Then, your `keymap.c` file, you'll need to define a sequence of keys, terminated with `COMBO_END`, and a structure to list the combination of keys, and it's resulting action. | |||
```c | |||
const uint16_t PROGMEM test_combo[] = {KC_A, KC_B, COMBO_END}; | |||
combo_t key_combos[COMBO_COUNT] = {COMBO(test_combo, KC_ESC)}; | |||
``` | |||
This will send "Escape" if you hit the A and B keys. | |||
!> This method only supports [basic keycodes](keycodes_basic.md). See the examples for more control. | |||
!> You cannot reuse (share) keys in combos. Each key should only belong to a single combo. | |||
## Examples | |||
If you want to add a list, then you'd use something like this: | |||
```c | |||
enum combos { | |||
AB_ESC, | |||
JK_TAB | |||
} | |||
const uint16_t PROGMEM ab_combo[] = {KC_A, KC_B, COMBO_END}; | |||
const uint16_t PROGMEM jk_combo[] = {KC_J, KC_K, COMBO_END}; | |||
combo_t key_combos[COMBO_COUNT] = { | |||
[AB_ESC] = COMBO(ab_combo, KC_ESC), | |||
[JK_TAB] = COMBO(jk_combo, KC_TAB) | |||
}; | |||
``` | |||
For a more complicated implementation, you can use the `process_combo_event` function to add custom handling. | |||
```c | |||
enum combo_events { | |||
ZC_COPY, | |||
XV_PASTE | |||
}; | |||
const uint16_t PROGMEM copy_combo[] = {KC_Z, KC_C, COMBO_END}; | |||
const uint16_t PROGMEM paste_combo[] = {KC_X, KC_V, COMBO_END}; | |||
combo_t key_combos[COMBO_COUNT] = { | |||
[ZC_COPY] = COMBO_ACTION(copy_combo), | |||
[XV_PASTE] = COMBO_ACTION(paste_combo), | |||
}; | |||
void process_combo_event(uint8_t combo_index, bool pressed) { | |||
switch(combo_index) { | |||
case ZC_COPY: | |||
if (pressed) { | |||
register_code(KC_LCTL); | |||
register_code(KC_C); | |||
unregister_code(KC_C); | |||
unregister_code(KC_LCTL); | |||
} | |||
break; | |||
case XV_PASTE: | |||
if (pressed) { | |||
register_code(KC_LCTL); | |||
register_code(KC_V); | |||
unregister_code(KC_V); | |||
unregister_code(KC_LCTL); | |||
} | |||
break; | |||
} | |||
} | |||
``` | |||
This will send Ctrl+C if you hit Z and C, and Ctrl+V if you hit X and V. But you could change this to do stuff like change layers, play sounds, or change settings. | |||
## Additional Configuration | |||
If you're using long combos, or even longer combos, you may run into issues with this, as the structure may not be large enough to accommodate what you're doing. | |||
In this case, you can add either `#define EXTRA_LONG_COMBOS` or `#define EXTRA_EXTRA_LONG_COMBOS` in your `config.h` file. | |||
You may also be able to enable action keys by defining `COMBO_ALLOW_ACTION_KEYS`. |
@ -0,0 +1,48 @@ | |||
# Encoders | |||
Basic encoders are supported by adding this to your `rules.mk`: | |||
ENCODER_ENABLE = yes | |||
and this to your `config.h`: | |||
#define NUMBER_OF_ENCODERS 1 | |||
#define ENCODERS_PAD_A { B12 } | |||
#define ENCODERS_PAD_B { B13 } | |||
Each PAD_A/B variable defines an array so multiple encoders can be defined, e.g.: | |||
#define ENCODERS_PAD_A { encoder1a, encoder2a } | |||
#define ENCODERS_PAD_B { encoder1b, encoder2b } | |||
If your encoder's clockwise directions are incorrect, you can swap the A & B pad definitions. | |||
Additionally, the resolution can be specified in the same file (the default & suggested is 4): | |||
#define ENCODER_RESOLUTION 4 | |||
## Callbacks | |||
The callback functions can be inserted into your `<keyboard>.c`: | |||
void encoder_update_kb(uint8_t index, bool clockwise) { | |||
encoder_update_user(index, clockwise); | |||
} | |||
or `keymap.c`: | |||
void encoder_update_user(uint8_t index, bool clockwise) { | |||
if (index == 0) { | |||
if (clockwise) { | |||
register_code(KC_PGDN); | |||
unregister_code(KC_PGDN); | |||
} else { | |||
register_code(KC_PGUP); | |||
unregister_code(KC_PGUP); | |||
} | |||
} | |||
} | |||
## Hardware | |||
The A an B lines of the encoders should be wired directly to the MCU, and the C/common lines should be wired to ground. |
@ -0,0 +1,82 @@ | |||
# I2C Master Driver | |||
The I2C Master drivers used in QMK have a set of common functions to allow portability between MCUs. | |||
## Available functions | |||
|Function |Description | | |||
|------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | |||
|`void i2c_init(void);` |Initializes the I2C driver. This function should be called once before any transaction is initiated. | | |||
|`uint8_t i2c_start(uint8_t address);` |Starts an I2C transaction. Address is the 7-bit slave address without the direction bit. | | |||
|`uint8_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);` |Transmit data over I2C. Address is the 7-bit slave address without the direction. Returns status of transaction. | | |||
|`uint8_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);` |Receive data over I2C. Address is the 7-bit slave address without the direction. Saves number of bytes specified by `length` in `data` array. Returns status of transaction. | | |||
|`uint8_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);` |Same as the `i2c_transmit` function but `regaddr` sets where in the slave the data will be written. | | |||
|`uint8_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);` |Same as the `i2c_receive` function but `regaddr` sets from where in the slave the data will be read. | | |||
|`uint8_t i2c_stop(uint16_t timeout);` |Stops the I2C driver. | | |||
### Function Return | |||
All the above functions, except `void i2c_init(void);` return the following truth table: | |||
|Return Value |Description | | |||
|---------------|---------------------------------------------------| | |||
|0 |Operation executed successfully. | | |||
|-1 |Operation failed. | | |||
|-2 |Operation timed out. | | |||
## AVR | |||
### Configuration | |||
The following defines can be used to configure the I2C master driver. | |||
|Variable |Description |Default| | |||
|------------------|---------------------------------------------------|-------| | |||
|`#F_SCL` |Clock frequency in Hz |400KHz | | |||
|`#Prescaler` |Divides master clock to aid in I2C clock selection |1 | | |||
AVRs usually have set GPIO which turn into I2C pins, therefore no further configuration is required. | |||
## ARM | |||
For ARM the Chibios I2C HAL driver is under the hood. | |||
This section assumes an STM32 MCU. | |||
### Configuration | |||
The configuration for ARM MCUs can be quite complex as often there are multiple I2C drivers which can be assigned to a variety of ports. | |||
Firstly the `mcuconf.h` file must be setup to enable the necessary hardware drivers. | |||
|Variable |Description |Default| | |||
|------------------------------|------------------------------------------------------------------------------------|-------| | |||
|`#STM32_I2C_USE_XXX` |Enable/Disable the hardware driver XXX (each driver should be explicitly listed) |FALSE | | |||
|`#STM32_I2C_BUSY_TIMEOUT` |Time in ms until the I2C command is aborted if no response is received |50 | | |||
|`#STM32_I2C_XXX_IRQ_PRIORITY` |Interrupt priority for hardware driver XXX (THIS IS AN EXPERT SETTING) |10 | | |||
|`#STM32_I2C_USE_DMA` |Enable/Disable the ability of the MCU to offload the data transfer to the DMA unit |TRUE | | |||
|`#STM32_I2C_XXX_DMA_PRIORITY` |Priority of DMA unit for hardware driver XXX (THIS IS AN EXPERT SETTING) |1 | | |||
Secondly, in the `halconf.h` file, `#define HAL_USE_I2C` must be set to `TRUE`. This allows ChibiOS to load its I2C driver. | |||
Lastly, we need to assign the correct GPIO pins depending on the I2C hardware driver we want to use. | |||
By default the I2C1 hardware driver is assumed to be used. If another hardware driver is used, `#define I2C_DRIVER I2CDX` should be added to the `config.h` file with X being the number of hardware driver used. For example is I2C3 is enabled, the `config.h` file should contain `#define I2C_DRIVER I2CD3`. This aligns the QMK I2C driver with the Chibios I2C driver. | |||
STM32 MCUs allows a variety of pins to be configured as I2C pins depending on the hardware driver used. By default B6 and B7 are set to I2C. | |||
This can be changed by declaring the `i2c_init` function which intentionally has a weak attribute. Please consult the datasheet of your MCU for the available GPIO configurations. The following is an example initialization function: | |||
```C | |||
void i2c_init(void) | |||
{ | |||
setPinInput(B6); // Try releasing special pins for a short time | |||
setPinInput(B7); | |||
chThdSleepMilliseconds(10); // Wait for the release to happen | |||
palSetPadMode(GPIOB, 6, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); // Set B6 to I2C function | |||
palSetPadMode(GPIOB, 7, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); // Set B7 to I2C function | |||
} | |||
``` | |||
@ -0,0 +1,23 @@ | |||
# GPIO Control | |||
QMK has a GPIO control abstraction layer which is micro-controller agnostic. This is done to allow easy access to pin control across different platforms. | |||
## Functions | |||
The following functions can provide basic control of GPIOs and are found in `quantum/quantum.h`. | |||
|Function |Description | | |||
|----------------------|------------------------------------------------------------------| | |||
|`setPinInput(pin)` |Set pin as input with high impedance (High-Z) | | |||
|`setPinInputHigh(pin)`|Set pin as input with build in pull-up | | |||
|`setPinInputLow(pin)` |Set pin as input with build in pull-down (Supported only on STM32)| | |||
|`setPinOutput(pin)` |Set pin as output | | |||
|`writePinHigh(pin)` |Set pin level as high, assuming it is an output | | |||
|`writePinLow(pin)` |Set pin level as low, assuming it is an output | | |||
|`writePin(pin, level)`|Set pin level, assuming it is an output | | |||
|`readPin(pin)` |Returns the level of the pin | | |||
## Advance settings | |||
Each micro-controller can have multiple advance settings regarding its GPIO. This abstraction layer does not limit the use of architecture specific functions. Advance users should consult the datasheet of there desired device and include any needed libraries. For AVR the standard avr/io.h library is used and for STM32 the Chibios [PAL library](http://chibios.sourceforge.net/docs3/hal/group___p_a_l.html) is used. | |||
@ -1,261 +0,0 @@ | |||
Keycode Symbol Table | |||
==================== | |||
Keycodes are defined in `common/keycode.h`. | |||
Range of 00-A4 and E0-E7 are identical with HID Usage: | |||
<http://www.usb.org/developers/hidpage/Hut1_12v2.pdf> | |||
Virtual keycodes are defined out of above range to support special actions. | |||
Keycode Symbol Short name Description | |||
-------------------------------------------------------------------------------- | |||
KC_NO 00 Reserved (no event indicated) | |||
KC_ROLL_OVER 01 Keyboard ErrorRollOver | |||
KC_POST_FAIL 02 Keyboard POSTFail | |||
KC_UNDEFINED 03 Keyboard ErrorUndefined | |||
KC_A 04 Keyboard a and A | |||
KC_B 05 Keyboard b and B | |||
KC_C 06 Keyboard c and C | |||
KC_D 07 Keyboard d and D | |||
KC_E 08 Keyboard e and E | |||
KC_F 09 Keyboard f and F | |||
KC_G 0A Keyboard g and G | |||
KC_H 0B Keyboard h and H | |||
KC_I 0C Keyboard i and I | |||
KC_J 0D Keyboard j and J | |||
KC_K 0E Keyboard k and K | |||
KC_L 0F Keyboard l and L | |||
KC_M 10 Keyboard m and M | |||
KC_N 11 Keyboard n and N | |||
KC_O 12 Keyboard o and O | |||
KC_P 13 Keyboard p and P | |||
KC_Q 14 Keyboard q and Q | |||
KC_R 15 Keyboard r and R | |||
KC_S 16 Keyboard s and S | |||
KC_T 17 Keyboard t and T | |||
KC_U 18 Keyboard u and U | |||
KC_V 19 Keyboard v and V | |||
KC_W 1A Keyboard w and W | |||
KC_X 1B Keyboard x and X | |||
KC_Y 1C Keyboard y and Y | |||
KC_Z 1D Keyboard z and Z | |||
KC_1 1E Keyboard 1 and ! | |||
KC_2 1F Keyboard 2 and @ | |||
KC_3 20 Keyboard 3 and # | |||
KC_4 21 Keyboard 4 and $ | |||
KC_5 22 Keyboard 5 and % | |||
KC_6 23 Keyboard 6 and ^ | |||
KC_7 24 Keyboard 7 and & | |||
KC_8 25 Keyboard 8 and * | |||
KC_9 26 Keyboard 9 and ( | |||
KC_0 27 Keyboard 0 and ) | |||
KC_ENTER KC_ENT 28 Keyboard Return (ENTER) | |||
KC_ESCAPE KC_ESC 29 Keyboard ESCAPE | |||
KC_BSPACE KC_BSPC 2A Keyboard DELETE (Backspace) | |||
KC_TAB 2B Keyboard Tab | |||
KC_SPACE KC_SPC 2C Keyboard Spacebar | |||
KC_MINUS KC_MINS 2D Keyboard - and (underscore) | |||
KC_EQUAL KC_EQL 2E Keyboard = and + | |||
KC_LBRACKET KC_LBRC 2F Keyboard [ and { | |||
KC_RBRACKET KC_RBRC 30 Keyboard ] and } | |||
KC_BSLASH KC_BSLS 31 Keyboard \ and | | |||
KC_NONUS_HASH KC_NUHS 32 Keyboard Non-US # and ~ | |||
KC_SCOLON KC_SCLN 33 Keyboard ; and : | |||
KC_QUOTE KC_QUOT 34 Keyboard ‘ and “ | |||
KC_GRAVE KC_GRV 35 Keyboard Grave Accent and Tilde | |||
KC_COMMA KC_COMM 36 Keyboard , and < | |||
KC_DOT 37 Keyboard . and > | |||
KC_SLASH KC_SLSH 38 Keyboard / and ? | |||
KC_CAPSLOCK KC_CAPS 39 Keyboard Caps Lock | |||
KC_F1 3A Keyboard F1 | |||
KC_F2 3B Keyboard F2 | |||
KC_F3 3C Keyboard F3 | |||
KC_F4 3D Keyboard F4 | |||
KC_F5 3E Keyboard F5 | |||
KC_F6 3F Keyboard F6 | |||
KC_F7 40 Keyboard F7 | |||
KC_F8 41 Keyboard F8 | |||
KC_F9 42 Keyboard F9 | |||
KC_F10 43 Keyboard F10 | |||
KC_F11 44 Keyboard F11 | |||
KC_F12 45 Keyboard F12 | |||
KC_PSCREEN KC_PSCR 46 Keyboard PrintScreen | |||
KC_SCROLLLOCK KC_SLCK 47 Keyboard Scroll Lock | |||
KC_PAUSE KC_PAUS 48 Keyboard Pause | |||
KC_INSERT KC_INS 49 Keyboard Insert | |||
KC_HOME 4A Keyboard Home | |||
KC_PGUP 4B Keyboard PageUp | |||
KC_DELETE KC_DEL 4C Keyboard Delete Forward | |||
KC_END 4D Keyboard End | |||
KC_PGDOWN KC_PGDN 4E Keyboard PageDown | |||
KC_RIGHT KC_RGHT 4F Keyboard RightArrow | |||
KC_LEFT 50 Keyboard LeftArrow | |||
KC_DOWN 51 Keyboard DownArrow | |||
KC_UP 52 Keyboard UpArrow | |||
KC_NUMLOCK KC_NLCK 53 Keypad Num Lock and Clear | |||
KC_KP_SLASH KC_PSLS 54 Keypad / | |||
KC_KP_ASTERISK KC_PAST 55 Keypad * | |||
KC_KP_MINUS KC_PMNS 56 Keypad - | |||
KC_KP_PLUS KC_PPLS 57 Keypad + | |||
KC_KP_ENTER KC_PENT 58 Keypad ENTER | |||
KC_KP_1 KC_P1 59 Keypad 1 and End | |||
KC_KP_2 KC_P2 5A Keypad 2 and Down Arrow | |||
KC_KP_3 KC_P3 5B Keypad 3 and PageDn | |||
KC_KP_4 KC_P4 5C Keypad 4 and Left Arrow | |||
KC_KP_5 KC_P5 5D Keypad 5 | |||
KC_KP_6 KC_P6 5E Keypad 6 and Right Arrow | |||
KC_KP_7 KC_P7 5F Keypad 7 and Home | |||
KC_KP_8 KC_P8 60 Keypad 8 and Up Arrow | |||
KC_KP_9 KC_P9 61 Keypad 9 and PageUp | |||
KC_KP_0 KC_P0 62 Keypad 0 and Insert | |||
KC_KP_DOT KC_PDOT 63 Keypad . and Delete | |||
KC_NONUS_BSLASH KC_NUBS 64 Keyboard Non-US \ and | | |||
KC_APPLICATION KC_APP 65 Keyboard Application | |||
KC_POWER 66 Keyboard Power | |||
KC_KP_EQUAL KC_PEQL 67 Keypad = | |||
KC_F13 68 Keyboard F13 | |||
KC_F14 69 Keyboard F14 | |||
KC_F15 6A Keyboard F15 | |||
KC_F16 6B Keyboard F16 | |||
KC_F17 6C Keyboard F17 | |||
KC_F18 6D Keyboard F18 | |||
KC_F19 6E Keyboard F19 | |||
KC_F20 6F Keyboard F20 | |||
KC_F21 70 Keyboard F21 | |||
KC_F22 71 Keyboard F22 | |||
KC_F23 72 Keyboard F23 | |||
KC_F24 73 Keyboard F24 | |||
KC_EXECUTE 74 Keyboard Execute | |||
KC_HELP 75 Keyboard Help | |||
KC_MENU 76 Keyboard Menu | |||
KC_SELECT 77 Keyboard Select | |||
KC_STOP 78 Keyboard Stop | |||
KC_AGAIN 79 Keyboard Again | |||
KC_UNDO 7A Keyboard Undo | |||
KC_CUT 7B Keyboard Cut | |||
KC_COPY 7C Keyboard Copy | |||
KC_PASTE 7D Keyboard Paste | |||
KC_FIND 7E Keyboard Find | |||
KC__MUTE 7F Keyboard Mute | |||
KC__VOLUP 80 Keyboard Volume Up | |||
KC__VOLDOWN 81 Keyboard Volume Down | |||
KC_LOCKING_CAPS 82 Keyboard Locking Caps Lock | |||
KC_LOCKING_NUM 83 Keyboard Locking Num Lock | |||
KC_LOCKING_SCROLL 84 Keyboard Locking Scroll Lock | |||
KC_KP_COMMA KC_PCMM 85 Keypad Comma | |||
KC_KP_EQUAL_AS400 86 Keypad Equal Sign | |||
KC_INT1 KC_RO 87 Keyboard International115 | |||
KC_INT2 KC_KANA 88 Keyboard International216 | |||
KC_INT3 KC_JYEN 89 Keyboard International317 | |||
KC_INT4 KC_HENK 8A Keyboard International418 | |||
KC_INT5 KC_MHEN 8B Keyboard International519 | |||
KC_INT6 8C Keyboard International620 | |||
KC_INT7 8D Keyboard International721 | |||
KC_INT8 8E Keyboard International822 | |||
KC_INT9 8F Keyboard International922 | |||
KC_LANG1 90 Keyboard LANG125 | |||
KC_LANG2 91 Keyboard LANG226 | |||
KC_LANG3 92 Keyboard LANG330 | |||
KC_LANG4 93 Keyboard LANG431 | |||
KC_LANG5 94 Keyboard LANG532 | |||
KC_LANG6 95 Keyboard LANG68 | |||
KC_LANG7 96 Keyboard LANG78 | |||
KC_LANG8 97 Keyboard LANG88 | |||
KC_LANG9 98 Keyboard LANG98 | |||
KC_ALT_ERASE 99 Keyboard Alternate Erase | |||
KC_SYSREQ 9A Keyboard SysReq/Attention | |||
KC_CANCEL 9B Keyboard Cancel | |||
KC_CLEAR 9C Keyboard Clear | |||
KC_PRIOR 9D Keyboard Prior | |||
KC_RETURN 9E Keyboard Return | |||
KC_SEPARATOR 9F Keyboard Separator | |||
KC_OUT A0 Keyboard Out | |||
KC_OPER A1 Keyboard Oper | |||
KC_CLEAR_AGAIN A2 Keyboard Clear/Again | |||
KC_CRSEL A3 Keyboard CrSel/Props | |||
KC_EXSEL A4 Keyboard ExSel | |||
/* Modifiers */ | |||
KC_LCTRL KC_LCTL E0 Keyboard LeftControl | |||
KC_LSHIFT KC_LSFT E1 Keyboard LeftShift | |||
KC_LALT E2 Keyboard LeftAlt | |||
KC_LGUI E3 Keyboard Left GUI(Windows/Apple/Meta key) | |||
KC_RCTRL KC_RCTL E4 Keyboard RightControl | |||
KC_RSHIFT KC_RSFT E5 Keyboard RightShift | |||
KC_RALT E6 Keyboard RightAlt | |||
KC_RGUI E7 Keyboard Right GUI(Windows/Apple/Meta key) | |||
/* | |||
* Virtual keycodes | |||
*/ | |||
/* System Control */ | |||
KC_SYSTEM_POWER KC_PWR System Power Down | |||
KC_SYSTEM_SLEEP KC_SLEP System Sleep | |||
KC_SYSTEM_WAKE KC_WAKE System Wake | |||
/* Consumer Page */ | |||
KC_AUDIO_MUTE KC_MUTE | |||
KC_AUDIO_VOL_UP KC_VOLU | |||
KC_AUDIO_VOL_DOWN KC_VOLD | |||
KC_MEDIA_NEXT_TRACK KC_MNXT | |||
KC_MEDIA_PREV_TRACK KC_MPRV | |||
KC_MEDIA_STOP KC_MSTP | |||
KC_MEDIA_PLAY_PAUSE KC_MPLY | |||
KC_MEDIA_SELECT KC_MSEL | |||
KC_MAIL KC_MAIL | |||
KC_CALCULATOR KC_CALC | |||
KC_MY_COMPUTER KC_MYCM | |||
KC_WWW_SEARCH KC_WSCH | |||
KC_WWW_HOME KC_WHOM | |||
KC_WWW_BACK KC_WBAK | |||
KC_WWW_FORWARD KC_WFWD | |||
KC_WWW_STOP KC_WSTP | |||
KC_WWW_REFRESH KC_WREF | |||
KC_WWW_FAVORITES KC_WFAV | |||
/* Mousekey */ | |||
KC_MS_UP KC_MS_U Mouse Cursor Up | |||
KC_MS_DOWN KC_MS_D Mouse Cursor Down | |||
KC_MS_LEFT KC_MS_L Mouse Cursor Left | |||
KC_MS_RIGHT KC_MS_R Mouse Cursor Right | |||
KC_MS_BTN1 KC_BTN1 Mouse Button 1 | |||
KC_MS_BTN2 KC_BTN2 Mouse Button 2 | |||
KC_MS_BTN3 KC_BTN3 Mouse Button 3 | |||
KC_MS_BTN4 KC_BTN4 Mouse Button 4 | |||
KC_MS_BTN5 KC_BTN5 Mouse Button 5 | |||
KC_MS_WH_UP KC_WH_U Mouse Wheel Up | |||
KC_MS_WH_DOWN KC_WH_D Mouse Wheel Down | |||
KC_MS_WH_LEFT KC_WH_L Mouse Wheel Left | |||
KC_MS_WH_RIGHT KC_WH_R Mouse Wheel Right | |||
KC_MS_ACCEL0 KC_ACL0 Mouse Acceleration 0 | |||
KC_MS_ACCEL1 KC_ACL1 Mouse Acceleration 1 | |||
KC_MS_ACCEL2 KC_ACL2 Mouse Acceleration 2 | |||
/* Fn key */ | |||
KC_FN0 | |||
KC_FN1 | |||
KC_FN2 | |||
KC_FN3 | |||
KC_FN4 | |||
KC_FN5 | |||
KC_FN6 | |||
KC_FN7 | |||
KC_FN8 | |||
KC_FN9 | |||
KC_FN10 | |||
KC_FN11 | |||
KC_FN12 | |||
KC_FN13 | |||
KC_FN14 | |||
KC_FN15 | |||
KC_FN16 | |||
KC_FN17 | |||
KC_FN18 | |||
KC_FN19 | |||
KC_FN20 | |||
KC_FN21 | |||
KC_FN22 | |||
KC_FN23 | |||
KC_FN24 | |||
KC_FN25 | |||
KC_FN26 | |||
KC_FN27 | |||
KC_FN28 | |||
KC_FN29 | |||
KC_FN30 | |||
KC_FN31 |
@ -0,0 +1,163 @@ | |||
# Best Practices | |||
## Or, "How I Learned to Stop Worrying and Love Git." | |||
This document aims to instruct novices in the best ways to have a smooth experience in contributing to QMK. We will walk through the process of contributing to QMK, detailing some ways to make this task easier, and then later we'll break some things in order to teach you how to fix them. | |||
This document assumes a few things: | |||
1. You have a GitHub account, and have [forked the qmk_firmware repository](getting_started_github.md) to your account. | |||
2. You've [set up your build environment](newbs_getting_started.md?id=environment-setup). | |||
## Your fork's master: Update Often, Commit Never | |||
It is highly recommended for QMK development, regardless of what is being done or where, to keep your `master` branch updated, but ***never*** commit to it. Instead, do all your changes in a development branch and issue pull requests from your branches when you're developing. | |||
To reduce the chances of merge conflicts — instances where two or more users have edited the same part of a file concurrently — keep your `master` branch relatively up-to-date, and start any new developments by creating a new branch. | |||
### Updating your master branch | |||
To keep your `master` branch updated, it is recommended to add the QMK Firmware repository ("repo") as a remote repository in git. To do this, open your Git command line interface and enter: | |||
``` | |||
git remote add upstream https://github.com/qmk/qmk_firmware.git | |||
``` | |||
To verify that the repository has been added, run `git remote -v`, which should return the following: | |||
``` | |||
$ git remote -v | |||
origin https://github.com/<your_username>/qmk_firmware.git (fetch) | |||
origin https://github.com/<your_username>/qmk_firmware.git (push) | |||
upstream https://github.com/qmk/qmk_firmware.git (fetch) | |||
upstream https://github.com/qmk/qmk_firmware.git (push) | |||
``` | |||
Now that this is done, you can check for updates to the repo by running `git fetch upstream`. This retrieves the branches and tags — collectively referred to as "refs" — from the QMK repo, which now has the nickname `upstream`. We can now compare the data on our fork `origin` to that held by QMK. | |||
To update your fork's master, run the following, hitting the Enter key after each line: | |||
``` | |||
git checkout master | |||
git fetch upstream | |||
git pull upstream master | |||
git push origin master | |||
``` | |||
This switches you to your `master` branch, retrieves the refs from the QMK repo, downloads the current QMK `master` branch to your computer, and then uploads it to your fork. | |||
### Making Changes | |||
To make changes, create a new branch by entering: | |||
``` | |||
git checkout -b dev_branch | |||
git push --set-upstream origin dev_branch | |||
``` | |||
This creates a new branch named `dev_branch`, checks it out, and then saves the new branch to your fork. The `--set-upstream` argument tells git to use your fork and the `dev_branch` branch every time you use `git push` or `git pull` from this branch. It only needs to be used on the first push; after that, you can safely use `git push` or `git pull`, without the rest of the arguments. | |||
!> With `git push`, you can use `-u` in place of `--set-upstream` — `-u` is an alias for `--set-upstream`. | |||
You can name your branch nearly anything you want, though it is recommended to name it something related to the changes you are going to make. | |||
By default `git checkout -b` will base your new branch on the branch that is checked out. You can base your new branch on an existing branch that is not checked out by adding the name of the existing branch to the command: | |||
``` | |||
git checkout -b dev_branch master | |||
``` | |||
Now that you have a development branch, open your text editor and make whatever changes you need to make. It is recommended to make many small commits to your branch; that way, any change that causes issues can be more easily traced and undone if needed. To make your changes, edit and save any files that need to be updated, add them to Git's *staging area*, and then commit them to your branch: | |||
``` | |||
git add path/to/updated_file | |||
git commit -m "My commit message." | |||
``` | |||
`git add` adds files that have been changed to Git's *staging area*, which is Git's "loading zone." This contains the changes that are going to be *committed* by `git commit`, which saves the changes to the repo. Use descriptive commit messages so you can know what was changed at a glance. | |||
!> If you've changed a lot of files, but all the files are part of the same change, you can use `git add .` to add all the changed files that are in your current directory, rather than having to add each file individually. | |||
### Publishing Your Changes | |||
The last step is to push your changes to your fork. To do this, enter `git push`. Git now publishes the current state of `dev_branch` to your fork. | |||
## Resolving Merge Conflicts | |||
Sometimes when your work in a branch takes a long time to complete, changes that have been made by others conflict with changes you have made to your branch when you open a pull request. This is called a *merge conflict*, and is what happens when multiple people edit the same parts of the same files. | |||
### Rebasing Your Changes | |||
A *rebase* is Git's way of taking changes that were applied at one point, reversing them, and then applying the same changes to another point. In the case of a merge conflict, you can rebase your branch to grab the changes that were made between when you created your branch and the present time. | |||
To start, run the following: | |||
``` | |||
git fetch upstream | |||
git rev-list --left-right --count HEAD...upstream/master | |||
``` | |||
The `git rev-list` command entered here returns the number of commits that differ between the current branch and QMK's master branch. We run `git fetch` first to make sure we have the refs that represent the current state of the upstream repo. The output of the `git rev-list` command entered returns two numbers: | |||
``` | |||
$ git rev-list --left-right --count HEAD...upstream/master | |||
7 35 | |||
``` | |||
The first number represents the number of commits on the current branch since it was created, and the second number is the number of commits made to `upstream/master` since the current branch was created, and thus, the changes that are not recorded in the current branch. | |||
Now that the current states of both the current branch and the upstream repo are known, we can start a rebase operation: | |||
``` | |||
git rebase upstream/master | |||
``` | |||
This tells Git to undo the commits on the current branch, and then reapply them against QMK's master branch. | |||
``` | |||
$ git rebase upstream/master | |||
First, rewinding head to replay your work on top of it... | |||
Applying: Commit #1 | |||
Using index info to reconstruct a base tree... | |||
M conflicting_file_1.txt | |||
Falling back to patching base and 3-way merge... | |||
Auto-merging conflicting_file_1.txt | |||
CONFLICT (content): Merge conflict in conflicting_file_1.txt | |||
error: Failed to merge in the changes. | |||
hint: Use 'git am --show-current-patch' to see the failed patch | |||
Patch failed at 0001 Commit #1 | |||
Resolve all conflicts manually, mark them as resolved with | |||
"git add/rm <conflicted_files>", then run "git rebase --continue". | |||
You can instead skip this commit: run "git rebase --skip". | |||
To abort and get back to the state before "git rebase", run "git rebase --abort". | |||
``` | |||
This tells us that we have a merge conflict, and gives the name of the file with the conflict. Open the conflicting file in your text editor, and somewhere in the file, you'll find something like this: | |||
``` | |||
<<<<<<< HEAD | |||
<p>For help with any issues, email us at support@webhost.us.</p> | |||
======= | |||
<p>Need help? Email support@webhost.us.</p> | |||
>>>>>>> Commit #1 | |||
``` | |||
The line `<<<<<<< HEAD` marks the beginning of a merge conflict, and the `>>>>>>> Commit #1` line marks the end, with the conflicting sections separated by `=======`. The part on the `HEAD` side is from the QMK master version of the file, and the part marked with the commit message is from the current branch and commit. | |||
Because Git tracks *changes to files* rather than the contents of the files directly, if Git can't find the text that was in the file previous to the commit that was made, it won't know how to edit the file. Re-editing the file will solve the conflict. Make your changes, and then save the file. | |||
``` | |||
<p>Need help? Email support@webhost.us.</p> | |||
``` | |||
Now run: | |||
``` | |||
git add conflicting_file_1.txt | |||
git rebase --continue | |||
``` | |||
Git logs the changes to the conflicting file, and continues applying the commits from our branch until it reaches the end. |
@ -1,99 +1,97 @@ | |||
# Introduction | |||
Your computer keyboard has a processor inside of it, not unlike the one inside your computer. This processor runs software that is responsible for detecting button presses and sending reports about the state of the keyboard when they are pressed or released. QMK fills the role of that software, detecting button presses and passing that information on to the host computer. When you build your custom layout you are creating the equivalent of an .exe for your keyboard. | |||
Your computer keyboard has a processor inside of it, not unlike the one inside your computer. This processor runs software that is responsible for detecting button presses and sending reports about the state of the keyboard when buttons are pressed or released. QMK fills the role of that software, detecting button presses and passing that information on to the host computer. When you build your custom keymap, you are creating the equivalent of an executable program for your keyboard. | |||
QMK tries to put a lot of power into your hands by making easy things easy, and hard things possible. You don't have to know how to program to create powerful layouts, you only have to follow a few simple syntax rules. | |||
QMK tries to put a lot of power into your hands by making easy things easy, and hard things possible. You don't have to know how to program to create powerful keymaps — you only have to follow a few simple syntax rules. | |||
# Getting Started | |||
Before you can build keymaps you need to install some software and setup your build environment. This only has to be done one time no matter how many keyboards you want to compile firmware for. | |||
Before you can build keymaps, you need to install some software and set up your build environment. This only has to be done once no matter how many keyboards you plan to compile firmware for. | |||
## Download Software | |||
### Text Editor | |||
You'll need a program that can edit and save **plain text** files. If you are on Windows you can make due with Notepad, and on Linux you can use Gedit, both of which are simple but functional text editors. On macOS be careful with TextEdit.app, it will not save plain text files unless you make sure to select "Make Plain text" from the "Format" menu, or you can use another program such as Sublime Text. | |||
You'll need a program that can edit and save **plain text** files. If you're on Windows you can make do with Notepad, and on Linux you can use gedit. Both of these are simple but functional text editors. On macOS, be careful with the default TextEdit app: it will not save plain text files unless you explicitly select _Make Plain Text_ from the _Format_ menu. | |||
You can also download and install a dedicated text editor like [Sublime Text](https://www.sublimetext.com/) or [VS Code](https://code.visualstudio.com/). This is probably the best way to go regardless of platform, as these programs are specifically made for editing code. | |||
?> Not sure which text editor to use? Laurence Bradford wrote [a great introduction](https://learntocodewith.me/programming/basics/text-editors/) to the subject. | |||
### QMK Toolbox | |||
QMK Toolbox is an optional graphical Windows and macOS program that allows you to both program and debug your custom keyboard. You will likely prefer it to easily flash your keyboard and receive the debugging messages that your keyboard will print. | |||
Download the files from the links below: | |||
For Windows: "qmk_toolbox.exe" or "qmk_toolbox_install.exe" (with installer) | |||
QMK Toolbox is an optional graphical program for Windows and macOS that allows you to both program and debug your custom keyboard. You will likely find it invaluable for easily flashing your keyboard and viewing debug messages that it prints. | |||
For Mac: "QMK.Toolbox.app.zip" or "QMK.Toolbox.pkg" (with installer) | |||
[Download the latest release here.](https://github.com/qmk/qmk_toolbox/releases/latest) | |||
* [Newest Release](https://github.com/qmk/qmk_toolbox/releases/latest) | |||
* [Source Code](https://github.com/qmk/qmk_toolbox/) | |||
* For Windows: `qmk_toolbox.exe` (portable) or `qmk_toolbox_install.exe` (installer) | |||
* For macOS: `QMK.Toolbox.app.zip` (portable) or `QMK.Toolbox.pkg` (installer) | |||
## Environment Setup | |||
## Set Up Your Environment | |||
We've tried to make QMK as easy to setup as possible. You only have to prepare your Linux or Unix environment and let QMK install the rest. | |||
We've tried to make QMK as easy to set up as possible. You only have to prepare your Linux or Unix environment, then let QMK install the rest. | |||
?> If you haven't worked with the Linux/Unix command line before there are a few basic concepts and commands you should learn. These resources will teach you enough to work with QMK:<br> | |||
?> If you haven't worked with the Linux/Unix command line before, there are a few basic concepts and commands you should learn. These resources will teach you enough to be able to work with QMK:<br> | |||
[Must Know Linux Commands](https://www.guru99.com/must-know-linux-commands.html)<br> | |||
[Some Basic Unix Commands](https://www.tjhsst.edu/~dhyatt/superap/unixcmd.html) | |||
### Windows | |||
You will need to install msys2 and git. | |||
You will need to install MSYS2 and Git. | |||
* Follow the installation instructions on the msys2 homepage: http://www.msys2.org | |||
* Close any open msys2 terminals, and open a new terminal | |||
* Install git by running this command: `pacman -S git` | |||
* Follow the installation instructions on the [MSYS2 homepage](http://www.msys2.org). | |||
* Close any open MSYS2 terminals and open a new MSYS2 MinGW 64-bit terminal. | |||
* Install Git by running this command: `pacman -S git`. | |||
### macOS | |||
You will need to install homebrew. Follow the instructions on the homebrew homepage: https://brew.sh | |||
You will need to install Homebrew. Follow the instructions on the [Homebrew homepage](https://brew.sh). | |||
After homebrew is installed continue with "Download QMK", following step "Setup QMK" runs a script that will install other packages. | |||
After Homebrew is installed, continue with _Set Up QMK_. In that step you will run a script that will install other packages. | |||
### Linux | |||
You will need to install git. It's extremely likely you already have it, but if not one of the following commands should install it: | |||
You will need to install Git. It's very likely that you already have it, but if not, one of the following commands should install it: | |||
* Debian/Ubuntu/Devuan: `apt-get install git` | |||
* Fedora/Redhat/Centos: `yum install git` | |||
* Debian / Ubuntu / Devuan: `apt-get install git` | |||
* Fedora / Red Hat / CentOS: `yum install git` | |||
* Arch: `pacman -S git` | |||
## Download QMK | |||
?> Docker is also an option on all platforms. [Click here for details.](getting_started_build_tools.md#docker) | |||
Once you have setup your Linux/Unix environment you are ready to download QMK. We will do this by using git to "clone" the QMK repository. Open a Terminal or MSYS2 Console window and leave it open for the remainder of this guide. Inside that window run these two commands: | |||
## Set Up QMK | |||
Once you have set up your Linux/Unix environment, you are ready to download QMK. We will do this by using Git to "clone" the QMK repository. Open a Terminal or MSYS2 MinGW window and leave it open for the remainder of this guide. Inside that window run these two commands: | |||
git clone https://github.com/qmk/qmk_firmware.git | |||
cd qmk_firmware | |||
?> If you already know [how to use GitHub](getting_started_github.md) we recommend you create and clone your own fork instead. If you don't know what that means you can safely ignore this message. | |||
## Setup QMK | |||
?> If you already know [how to use GitHub](getting_started_github.md), we recommend that you create and clone your own fork instead. If you don't know what that means, you can safely ignore this message. | |||
QMK comes with a script to help you setup the rest of what you'll need. You should run it now by typing in this command: | |||
QMK comes with a script to help you set up the rest of what you'll need. You should run it now by typing in this command: | |||
./util/qmk_install.sh | |||
util/qmk_install.sh | |||
## Test Your Build Environment | |||
Now that your QMK build environment is setup you can build a firmware for your keyboard. Start by trying to build the default layout for your keyboard. You should be able to do that with a command in this format: | |||
Now that your QMK build environment is set up, you can build a firmware for your keyboard. Start by trying to build the keyboard's default keymap. You should be able to do that with a command in this format: | |||
make <keyboard>:default | |||
For example, to build a firmware for a Clueboard 66% use: | |||
For example, to build a firmware for a Clueboard 66% you would use: | |||
make clueboard/66/rev3:default | |||
When it is done you should have a lot of output that ends similar to this: | |||
``` | |||
Linking: .build/clueboard_66_rev2_default.elf [OK] | |||
Creating load file for flashing: .build/clueboard_66_rev2_default.hex [OK] | |||
Copying clueboard_66_rev2_default.hex to qmk_firmware folder [OK] | |||
Checking file size of clueboard_66_rev2_default.hex [OK] | |||
* File size is fine - 25174/28672 | |||
Linking: .build/clueboard_66_rev3_default.elf [OK] | |||
Creating load file for flashing: .build/clueboard_66_rev3_default.hex [OK] | |||
Copying clueboard_66_rev3_default.hex to qmk_firmware folder [OK] | |||
Checking file size of clueboard_66_rev3_default.hex [OK] | |||
* The firmware size is fine - 26356/28672 (2316 bytes free) | |||
``` | |||
## Creating Your Layout | |||
# Creating Your Keymap | |||
Now you are ready to create your own personal layout. Move on to [Building Your First Firmware](newbs_building_firmware.md) for that. | |||
You are now ready to create your own personal keymap! Move on to [Building Your First Firmware](newbs_building_firmware.md) for that. |
@ -1,13 +1,15 @@ | |||
# Learning Resources | |||
These resources are aimed at giving new members in the qmk community more understanding to the information provided in the newbs docs. | |||
These resources are aimed at giving new members in the QMK community more understanding to the information provided in the Newbs docs. | |||
Git resources: | |||
* | |||
*[Great General Tutorial](https://www.codecademy.com/learn/learn-git) | |||
*[Git Game To Learn From Examples](https://learngitbranching.js.org/) | |||
*[Git Resources to Learn More About Github](getting_started_github.md) | |||
*[Git Resources Aimed Specificly toward QMK](contributing.md) | |||
* [Great General Tutorial](https://www.codecademy.com/learn/learn-git) | |||
* [Git Game To Learn From Examples](https://learngitbranching.js.org/) | |||
* [Git Resources to Learn More About Github](getting_started_github.md) | |||
* [Git Resources Aimed Specifically toward QMK](contributing.md) | |||
Command Line resources: | |||
*[Good General Tutorial on Command Line](https://www.codecademy.com/learn/learn-the-command-line) | |||
* [Good General Tutorial on Command Line](https://www.codecademy.com/learn/learn-the-command-line) |
@ -0,0 +1,195 @@ | |||
# Supporting Your Keyboard in QMK Configurator | |||
This page covers how to properly support keyboards in the [QMK Configurator](https://config.qmk.fm/). | |||
## How the Configurator Understands Keyboards | |||
To understand how the Configurator understands keyboards, first one must understand layout macros. For this exercise, we're going to imagine a 17-key numpad PCB, which we're going to call `numpad`. | |||
``` | |||
┌───┬───┬───┬───┐ | |||
│NLk│ / │ * │ - │ | |||
├───┼───┼───┼───┤ | |||
│7 │8 │9 │ + │ | |||
├───┼───┼───┤ │ | |||
│4 │5 │6 │ │ | |||
├───┼───┼───┼───┤ | |||
│1 │2 │3 │Ent│ | |||
├───┴───┼───┤ │ | |||
│0 │ . │ │ | |||
└───────┴───┴───┘ | |||
``` | |||
?> For more on layout macros, see [Understanding QMK: Matrix Scanning](understanding_qmk.md?id=matrix-scanning) and [Understanding QMK: Matrix to Physical Layout Map](understanding_qmk.md?id=matrix-to-physical-layout-map). | |||
The Configurator's API reads the keyboard's `.h` file from `qmk_firmware/keyboards/<keyboard>/<keyboard>.h`. For our numpad, this file would be `qmk_firmware/keyboards/numpad/numpad.h`: | |||
```c | |||
#pragma once | |||
#define LAYOUT( \ | |||
k00, k01, k02, k03, \ | |||
k10, k11, k12, k13, \ | |||
k20, k21, k22, \ | |||
k30, k31, k32, k33, \ | |||
k40, k42 \ | |||
) { \ | |||
{ k00, k01, k02, k03 }, \ | |||
{ k10, k11, k12, k13 }, \ | |||
{ k20, k21, k22, KC_NO }, \ | |||
{ k30, k31, k32, k33 }, \ | |||
{ k40, KC_NO, k42, KC_NO } \ | |||
} | |||
``` | |||
QMK uses `KC_NO` to designate places in the switch matrix where there is no switch. Sometimes, `XXX`, `___` or `____` are used as shorthand to make this section easier to read if it needs to be debugged. This is usually defined near the beginning of the `.h` file: | |||
```c | |||
#pragma once | |||
#define XXX KC_NO | |||
#define LAYOUT( \ | |||
k00, k01, k02, k03, \ | |||
k10, k11, k12, k13, \ | |||
k20, k21, k22, \ | |||
k30, k31, k32, k33, \ | |||
k40, k42 \ | |||
) { \ | |||
{ k00, k01, k02, k03 }, \ | |||
{ k10, k11, k12, k13 }, \ | |||
{ k20, k21, k22, XXX }, \ | |||
{ k30, k31, k32, k33 }, \ | |||
{ k40, XXX, k42, XXX } \ | |||
} | |||
``` | |||
!> This usage differs from that of keymap macros, which almost always use `XXXXXXX` (seven capital X's) for `KC_NO` and `_______` (seven underscores) for `KC_TRNS`. | |||
!> To prevent user confusion, using `KC_NO` is preferred. | |||
The layout macro tells the Configurator that our keyboard has 17 keys, arranged in five rows of four columns each. Our switch positions are named `k<row><column>`, counting from 0. The names themselves actually don't matter, as long as they match between the top section, which receives the keycodes from the keymap, and the bottom half which designates where each key is in the matrix. | |||
To display our keyboard in a way that resembles the physical keyboard, we need to build a JSON file that tells the Configurator how to tie the physical locations and sizes of our keys to our switch matrix. | |||
## Building the JSON file | |||
To build the JSON file, the easiest way is to build the layout in [Keyboard Layout Editor](http://www.keyboard-layout-editor.com/) ("KLE"), from which we'll feed the Raw Data into a QMK tool that converts this data into a JSON the Configurator will read and use. Since KLE opens by default with a numpad layout, we're just going to remove the Getting Started instructions, and use what's left. | |||
Once the layout is as desired, move to the Raw Data tab in KLE, and copy the contents: | |||
``` | |||
["Num Lock","/","*","-"], | |||
["7\nHome","8\n↑","9\nPgUp",{h:2},"+"], | |||
["4\n←","5","6\n→"], | |||
["1\nEnd","2\n↓","3\nPgDn",{h:2},"Enter"], | |||
[{w:2},"0\nIns",".\nDel"] | |||
``` | |||
To convert this data into our JSON, go to the [QMK KLE-JSON Converter](https://qmk.fm/converter/), paste the Raw Data into the Input field, and click the Convert button. After a moment, our JSON data will appear in the Output field. Copy the contents to a new text document, and name the document `info.json`, saving it in the same folder that contains `numpad.h`. | |||
Use the `keyboard_name` object to set the name of the keyboard. The `bootloader` object is deprecated, so it can be deleted. For instruction purposes, we will put each key's object on its own line. This is only to make the file more human-readable, and does not affect the Configurator's functionality. | |||
```json | |||
{ | |||
"keyboard_name": "Numpad", | |||
"url": "", | |||
"maintainer": "qmk", | |||
"tags": { | |||
"form_factor": "numpad" | |||
}, | |||
"width": 4, | |||
"height": 5, | |||
"layouts": { | |||
"LAYOUT": { | |||
"layout": [ | |||
{"label":"Num Lock", "x":0, "y":0}, | |||
{"label":"/", "x":1, "y":0}, | |||
{"label":"*", "x":2, "y":0}, | |||
{"label":"-", "x":3, "y":0}, | |||
{"label":"7", "x":0, "y":1}, | |||
{"label":"8", "x":1, "y":1}, | |||
{"label":"9", "x":2, "y":1}, | |||
{"label":"+", "x":3, "y":1, "h":2}, | |||
{"label":"4", "x":0, "y":2}, | |||
{"label":"5", "x":1, "y":2}, | |||
{"label":"6", "x":2, "y":2}, | |||
{"label":"1", "x":0, "y":3}, | |||
{"label":"2", "x":1, "y":3}, | |||
{"label":"3", "x":2, "y":3}, | |||
{"label":"Enter", "x":3, "y":3, "h":2}, | |||
{"label":"0", "x":0, "y":4, "w":2}, | |||
{"label":".", "x":2, "y":4} | |||
] | |||
} | |||
} | |||
} | |||
``` | |||
The `layouts` object contains the data that represents the physical layout of the keyboard. It has an object `LAYOUT`, which needs to match the name of our layout macro from `numpad.h`. The `LAYOUT` object itself has an object named `layout`, which contains one JSON object for each physical key on our keyboard, formatted as follows: | |||
``` | |||
┌ The name of the key. Not displayed in the Configurator. | |||
│ ┌ The key's X-axis location, in key units from the | |||
│ │ keyboard's left edge. | |||
│ │ ┌ The key's Y-axis location, in key units from | |||
│ │ │ the keyboard's top (rear-facing) edge. | |||
↓ ↓ ↓ | |||
{"label":"Num Lock", "x":0, "y":0}, | |||
``` | |||
Some objects will also have `"w"` and `"h"` keys, which represent a key's width and height, respectively. | |||
?> For more on the `info.json` files, see [QMK Keyboard Guidelines: Keyboard Metadata](hardware_keyboard_guidelines.md?id=keyboard-metadata) | |||
## How the Configurator Programs Keys | |||
The Configurator's API uses the layout macro and the JSON file we've given it to create a visual representation of the keyboard that has each visual object tied to a specific key, in sequence: | |||
key in layout macro | JSON object used | |||
:---: | :---- | |||
k00 | {"label":"Num Lock", "x":0, "y":0} | |||
k01 | {"label":"/", "x":1, "y":0} | |||
k02 | {"label":"*", "x":2, "y":0} | |||
k03 | {"label":"-", "x":3, "y":0} | |||
k10 | {"label":"7", "x":0, "y":1} | |||
k11 | {"label":"8", "x":1, "y":1} | |||
k12 | {"label":"9", "x":2, "y":1} | |||
k13 | {"label":"+", "x":3, "y":1, "h":2} | |||
k20 | {"label":"4", "x":0, "y":2} | |||
k21 | {"label":"5", "x":1, "y":2} | |||
k22 | {"label":"6", "x":2, "y":2} | |||
k30 | {"label":"1", "x":0, "y":3} | |||
k31 | {"label":"2", "x":1, "y":3} | |||
k32 | {"label":"3", "x":2, "y":3} | |||
k33 | {"label":"Enter", "x":3, "y":3, "h":2} | |||
k40 | {"label":"0", "x":0, "y":4, "w":2} | |||
k42 | {"label":".", "x":2, "y":4} | |||
When a user selects the top-left key in the Configurator, and assigns Num Lock to it, the Configurator builds a keymap file with `KC_NLCK` as the first key, and so on as the keymap is built. The `label` keys are not used; they are only for the user's reference in identifying specific keys when debugging the `info.json` file. | |||
## Issues and Hazards | |||
Currently, the Configurator does not support key rotation or non-rectangular key shapes like ISO Enter. Additionally, keys that are vertically-offset from their "row" — the arrow keys on 1800-layouts like the [TKC1800](https://github.com/qmk/qmk_firmware/tree/4ac48a61a66206beaf2fdd5f2939d8bbedd0004c/keyboards/tkc1800/) being a prominent example — confuse the KLE-to-JSON Converter, if not adjusted for by the contributor of the `info.json` file. | |||
### Workarounds | |||
#### Non-rectangular keys | |||
For ISO Enter keys, QMK custom is to display it as a rectangular key, 1.25u wide and 2u high, aligned so its right edge is aligned with the right edge of the alphanumeric key block. | |||
![](https://i.imgur.com/JKngtTw.png) | |||
*A 60% keyboard in standard ISO layout, as rendered by QMK Configurator.* | |||
#### Vertically-offset keys | |||
For vertically-offset keys, place them in KLE as if they were not offset, then edit the Y-values as needed in the converted JSON file | |||
![](https://i.imgur.com/fmDvDzR.png) | |||
*An 1800-layout keyboard as rendered in Keyboard Layout Editor, without the vertical offset applied to the arrow keys.* | |||
![](https://i.imgur.com/8beYMBR.png) | |||
*A Unix diff file, showing the changes needed to vertically-offset the arrow keys in our keyboard's JSON file.* |
@ -0,0 +1,43 @@ | |||
# Support | |||
If you need help with something, the best place to get quick support is going to be on our [Discord Server](https://discord.gg/Uq7gcHh). There is usually somebody online, and there are a bunch of very helpful people there. | |||
Don't forget to read our [Code of Conduct](https://qmk.fm/coc/). | |||
## Help! I don't know where to start! | |||
If this is the case, then you should start with our [Newbs Guide](https://docs.qmk.fm/#/newbs). There is a lot of great info there, and that should cover everything you need to get started. | |||
If that's an issue, hop onto the [QMK Configurator](https://config.qmk.fm), as that will handle a majority of what you need there. | |||
## Help! I'm having issues flashing! | |||
First, head to the [Compiling/Flashing FAQ Page](https://docs.qmk.fm/#/faq_build). There is a good deal of info there, and you'll find a bunch of solutions to common issues there. | |||
## Help, I have an issue that isn't covered by the links above | |||
Okay, that's fine. Then please check the [open issues in our GitHub](https://github.com/qmk/qmk_firmware/issues) to see if somebody is experiencing the same thing (make sure it's not just similar, but actually the same). | |||
If you can't find anything, then please open a [new issue](https://github.com/qmk/qmk_firmware/issues/new)! | |||
## What if I found a bug? | |||
Then please open an [issue](https://github.com/qmk/qmk_firmware/issues/new), and if you know how to fix it, open up a Pull Request on GitHub with the fix. | |||
## But `git` and `GitHub` are intimidating! | |||
Don't worry, we have some pretty nice [Guidelines](https://docs.qmk.fm/#/newbs_best_practices) on how to start using `git` and GitHub to make things easier to develop. | |||
Additionally, you can find additional `git` and GitHub related links [here](https://docs.qmk.fm/#/newbs_learn_more_resources). | |||
## I have a Keyboard that I want to add support for | |||
Awesome! Open up a Pull Request for it. We'll review the code, and merge it! | |||
### What if I want to do brand it with `QMK`? | |||
That's amazing! We would love to assist you with that! | |||
In fact, we have a [whole page](https://qmk.fm/powered/) dedicated to adding QMK Branding to your page and keyboard. This covers pretty much everything you need (knowledge and images) to officially support QMK. | |||
If you have any questions about this, open an issue or head to [Discord](https://discord.gg/Uq7gcHh). |
@ -0,0 +1,32 @@ | |||
# QMK鍵盤固件 | |||
[![當前版本](https://img.shields.io/github/tag/qmk/qmk_firmware.svg)](https://github.com/qmk/qmk_firmware/tags) | |||
[![築邦](https://travis-ci.org/qmk/qmk_firmware.svg?branch=master)](https://travis-ci.org/qmk/qmk_firmware) | |||
[![不和諧](https://img.shields.io/discord/440868230475677696.svg)](https://discord.gg/Uq7gcHh) | |||
[![文檔狀態](https://img.shields.io/badge/docs-ready-orange.svg)](https://docs.qmk.fm) | |||
[![GitHub的貢獻者](https://img.shields.io/github/contributors/qmk/qmk_firmware.svg)](https://github.com/qmk/qmk_firmware/pulse/monthly) | |||
[![GitHub的叉](https://img.shields.io/github/forks/qmk/qmk_firmware.svg?style=social&label=Fork)](https://github.com/qmk/qmk_firmware/) | |||
## 什麼是QMK固件? | |||
QMK是一個由社群維護的開源鍵盤韌體,其中包含了QMK Toolbox、qmk.fm和其它文件。QMK韌體是以[tmk\_keyboard](http://github.com/tmk/tmk_keyboard)為基礎,讓一些有用的功能在Atmel AVR控制器實現,使用於[OLKB](https://olkb.com)、[ergodox EZ](http://www.ergodox-ez.com),和[Clueboard](http://clueboard.co/)的產品中。它也被移植到使用ChibiOS的ARM晶片上。你也可以用它來讓你徒手佈線,或是客製的鍵盤PCB發揮功能。 | |||
## 如何得到QMK | |||
如果你打算貢獻鍵盤佈局,鍵盤或功能QMK,最容易做的事情是[叉通過Github上爬行](https://github.com/qmk/qmk_firmware#fork-destination-box),和克隆你爬在本地進行更改,推動他們,然後打開從你的叉子[拉請求](https://github.com/qmk/qmk_firmware/pulls)。 | |||
否則,您可以直接下載([拉鍊](https://github.com/qmk/qmk_firmware/zipball/master) [焦油](https://github.com/qmk/qmk_firmware/tarball/master)),或者通過GIT中克隆它(`git@github.com:qmk/qmk_firmware.git`)或HTTP(`https://github.com/qmk/qmk_firmware.git`)。 | |||
## 如何編譯 | |||
你可以編譯之前,你需要[安裝環境](getting_started_build_tools.md)用於AVR或/和ARM開發。一旦完成,你會使用`make`命令建立一個鍵盤並用以下符號鍵盤佈局 | |||
make planck/rev4:default | |||
這將建立`rev4` `planck`的修訂與`default`鍵盤映射。並非所有鍵盤有一個修訂版(也稱為子項目或文件夾),在這種情況下,它可以被省略: | |||
make preonic:default | |||
## 如何赶近 | |||
QMK有很多[特點](features.md)探索和很好的協議[參考文獻](http://docs.qmk.fm)挖通的。大部分功能通過修改[鍵盤映射(keymap.md),並改變[鍵碼](keycodes.md)冤大頭。 |
@ -0,0 +1,99 @@ | |||
* [完全指南菜鳥](zh/newbs.md) | |||
* [入門](zh/newbs_getting_started.md) | |||
* [構建第一個固件](zh/newbs_building_firmware.md) | |||
* [刷新固件](zh/newbs_flashing.md) | |||
* [測試和調試](zh/newbs_testing_debugging.md) | |||
* [最佳實踐](zh/newbs_best_practices.md) | |||
* [學習資源](zh/newbs_learn_more_resources.md) | |||
* [QMK基礎](zh/README.md) | |||
* [QMK簡介](zh/getting_started_introduction.md) | |||
* [特約QMK](zh/contributing.md) | |||
* [如何使用Github上](zh/getting_started_github.md) | |||
* [獲得幫助](zh/getting_started_getting_help.md) | |||
* [常問問題](zh/faq.md) | |||
* [常問問題](zh/faq_general.md) | |||
* [構建/編譯QMK](zh/faq_build.md) | |||
* [調試/故障排除QMK](zh/faq_debug.md) | |||
* [鍵盤佈局](zh/faq_keymap.md) | |||
* 詳細指南 | |||
* [安裝編譯工具](zh/getting_started_build_tools.md) | |||
* [流浪漢指南](zh/getting_started_vagrant.md) | |||
* [構建/編譯器指令](zh/getting_started_make_guide.md) | |||
* [刷新固件](zh/flashing.md) | |||
* [定制功能](zh/custom_quantum_functions.md) | |||
* [鍵盤映射概述](zh/keymap.md) | |||
* [硬件](zh/hardware.md) | |||
* [AVR處理器](zh/hardware_avr.md) | |||
* [司機](zh/hardware_drivers.md) | |||
* 參考 | |||
* [Keyboard Guidelines](zh/hardware_keyboard_guidelines.md) | |||
* [Config Options](zh/config_options.md) | |||
* [Keycodes](zh/keycodes.md) | |||
* [Documentation Best Practices](zh/documentation_best_practices.md) | |||
* [Documentation Templates](zh/documentation_templates.md) | |||
* [Glossary](zh/reference_glossary.md) | |||
* [Unit Testing](zh/unit_testing.md) | |||
* [Useful Functions](zh/ref_functions.md) | |||
* [Configurator Support](zh/reference_configurator_support.md) | |||
* [特點](zh/features.md) | |||
* [Basic Keycodes](zh/keycodes_basic.md) | |||
* [Quantum Keycodes](zh/quantum_keycodes.md) | |||
* [Advanced Keycodes](zh/feature_advanced_keycodes.md) | |||
* [Audio](zh/feature_audio.md) | |||
* [Auto Shift](zh/feature_auto_shift.md) | |||
* [Backlight](zh/feature_backlight.md) | |||
* [Bluetooth](zh/feature_bluetooth.md) | |||
* [Bootmagic](zh/feature_bootmagic.md) | |||
* [Combos](zh/feature_combo) | |||
* [Command](zh/feature_command.md) | |||
* [Dynamic Macros](zh/feature_dynamic_macros.md) | |||
* [Encoders](zh/feature_encoders.md) | |||
* [Grave Escape](zh/feature_grave_esc.md) | |||
* [Key Lock](zh/feature_key_lock.md) | |||
* [Layouts](zh/feature_layouts.md) | |||
* [Leader Key](zh/feature_leader_key.md) | |||
* [Macros](zh/feature_macros.md) | |||
* [Mouse Keys](zh/feature_mouse_keys.md) | |||
* [One Shot Keys](zh/feature_advanced_keycodes.md#one-shot-keys) | |||
* [Pointing Device](zh/feature_pointing_device.md) | |||
* [PS/2 Mouse](zh/feature_ps2_mouse.md) | |||
* [RGB Lighting](zh/feature_rgblight.md) | |||
* [RGB Matrix](zh/feature_rgb_matrix.md) | |||
* [Space Cadet Shift](zh/feature_space_cadet_shift.md) | |||
* [Space Cadet Shift Enter](zh/feature_space_cadet_shift_enter.md) | |||
* [Stenography](zh/feature_stenography.md) | |||
* [Swap Hands](zh/feature_swap_hands.md) | |||
* [Tap Dance](zh/feature_tap_dance.md) | |||
* [Terminal](zh/feature_terminal.md) | |||
* [Thermal Printer](zh/feature_thermal_printer.md) | |||
* [Unicode](zh/feature_unicode.md) | |||
* [Userspace](zh/feature_userspace.md) | |||
* [US ANSI Shifted Keys](zh/keycodes_us_ansi_shifted.md) | |||
* 對於製造商和遊戲模組 | |||
* [Hand Wiring Guide](zh/hand_wire.md) | |||
* [ISP Flashing Guide](zh/isp_flashing_guide.md) | |||
* [ARM Debugging Guide](zh/arm_debugging.md) | |||
* [I2C Driver](zh/i2c_driver.md) | |||
* 為了更深入的了解 | |||
* [How Keyboards Work](zh/how_keyboards_work.md) | |||
* [Understanding QMK](zh/understanding_qmk.md) | |||
* 其它主題 | |||
* [Using Eclipse with QMK](zh/eclipse.md) | |||
* QMK內部(進行中) | |||
* [Defines](zh/internals_defines.md) | |||
* [Input Callback Reg](zh/internals_input_callback_reg.md) | |||
* [Midi Device](zh/internals_midi_device.md) | |||
* [Midi Device Setup Process](zh/internals_midi_device_setup_process.md) | |||
* [Midi Util](zh/internals_midi_util.md) | |||
* [Send Functions](zh/internals_send_functions.md) | |||
* [Sysex Tools](zh/internals_sysex_tools.md) |
@ -0,0 +1,129 @@ | |||
/* Copyright 2018 ishtob | |||
* Driver for DRV2605L written for QMK | |||
* | |||
* 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 "DRV2605L.h" | |||
#include "print.h" | |||
#include <stdlib.h> | |||
#include <stdio.h> | |||
#include <math.h> | |||
uint8_t DRV2605L_transfer_buffer[20]; | |||
uint8_t DRV2605L_tx_register[0]; | |||
uint8_t DRV2605L_read_buffer[0]; | |||
uint8_t DRV2605L_read_register; | |||
void DRV_write(uint8_t drv_register, uint8_t settings) { | |||
DRV2605L_transfer_buffer[0] = drv_register; | |||
DRV2605L_transfer_buffer[1] = settings; | |||
i2c_transmit(DRV2605L_BASE_ADDRESS << 1, DRV2605L_transfer_buffer, 2, 100); | |||
} | |||
uint8_t DRV_read(uint8_t regaddress) { | |||
DRV2605L_tx_register[0] = regaddress; | |||
if (MSG_OK != i2c_transmit_receive(DRV2605L_BASE_ADDRESS << 1, | |||
DRV2605L_tx_register, 1, | |||
DRV2605L_read_buffer, 1 | |||
)){ | |||
printf("err reading reg \n"); | |||
} | |||
DRV2605L_read_register = (uint8_t)DRV2605L_read_buffer[0]; | |||
return DRV2605L_read_register; | |||
} | |||
void DRV_init(void) | |||
{ | |||
i2c_init(); | |||
i2c_start(DRV2605L_BASE_ADDRESS); | |||
/* 0x07 sets DRV2605 into calibration mode */ | |||
DRV_write(DRV_MODE,0x07); | |||
// DRV_write(DRV_FEEDBACK_CTRL,0xB6); | |||
#if FB_ERM_LRA == 0 | |||
/* ERM settings */ | |||
DRV_write(DRV_RATED_VOLT, (RATED_VOLTAGE/21.33)*1000); | |||
#if ERM_OPEN_LOOP == 0 | |||
DRV_write(DRV_OVERDRIVE_CLAMP_VOLT, (((V_PEAK*(DRIVE_TIME+BLANKING_TIME+IDISS_TIME))/0.02133)/(DRIVE_TIME-0.0003))); | |||
#elif ERM_OPEN_LOOP == 1 | |||
DRV_write(DRV_OVERDRIVE_CLAMP_VOLT, (V_PEAK/0.02196)); | |||
#endif | |||
#elif FB_ERM_LRA == 1 | |||
DRV_write(DRV_RATED_VOLT, ((V_RMS * sqrt(1 - ((4 * ((150+(SAMPLE_TIME*50))*0.000001)) + 0.0003)* F_LRA)/0.02071))); | |||
#if LRA_OPEN_LOOP == 0 | |||
DRV_write(DRV_OVERDRIVE_CLAMP_VOLT, ((V_PEAK/sqrt(1-(F_LRA*0.0008))/0.02133))); | |||
#elif LRA_OPEN_LOOP == 1 | |||
DRV_write(DRV_OVERDRIVE_CLAMP_VOLT, (V_PEAK/0.02196)); | |||
#endif | |||
#endif | |||
DRVREG_FBR FB_SET; | |||
FB_SET.Bits.ERM_LRA = FB_ERM_LRA; | |||
FB_SET.Bits.BRAKE_FACTOR = FB_BRAKEFACTOR; | |||
FB_SET.Bits.LOOP_GAIN =FB_LOOPGAIN; | |||
FB_SET.Bits.BEMF_GAIN = 0; /* auto-calibration populates this field*/ | |||
DRV_write(DRV_FEEDBACK_CTRL, (uint8_t) FB_SET.Byte); | |||
DRVREG_CTRL1 C1_SET; | |||
C1_SET.Bits.C1_DRIVE_TIME = DRIVE_TIME; | |||
C1_SET.Bits.C1_AC_COUPLE = AC_COUPLE; | |||
C1_SET.Bits.C1_STARTUP_BOOST = STARTUP_BOOST; | |||
DRV_write(DRV_CTRL_1, (uint8_t) C1_SET.Byte); | |||
DRVREG_CTRL2 C2_SET; | |||
C2_SET.Bits.C2_BIDIR_INPUT = BIDIR_INPUT; | |||
C2_SET.Bits.C2_BRAKE_STAB = BRAKE_STAB; | |||
C2_SET.Bits.C2_SAMPLE_TIME = SAMPLE_TIME; | |||
C2_SET.Bits.C2_BLANKING_TIME = BLANKING_TIME; | |||
C2_SET.Bits.C2_IDISS_TIME = IDISS_TIME; | |||
DRV_write(DRV_CTRL_2, (uint8_t) C2_SET.Byte); | |||
DRVREG_CTRL3 C3_SET; | |||
C3_SET.Bits.C3_LRA_OPEN_LOOP = LRA_OPEN_LOOP; | |||
C3_SET.Bits.C3_N_PWM_ANALOG = N_PWM_ANALOG; | |||
C3_SET.Bits.C3_LRA_DRIVE_MODE = LRA_DRIVE_MODE; | |||
C3_SET.Bits.C3_DATA_FORMAT_RTO = DATA_FORMAT_RTO; | |||
C3_SET.Bits.C3_SUPPLY_COMP_DIS = SUPPLY_COMP_DIS; | |||
C3_SET.Bits.C3_ERM_OPEN_LOOP = ERM_OPEN_LOOP; | |||
C3_SET.Bits.C3_NG_THRESH = NG_THRESH; | |||
DRV_write(DRV_CTRL_3, (uint8_t) C3_SET.Byte); | |||
DRVREG_CTRL4 C4_SET; | |||
C4_SET.Bits.C4_ZC_DET_TIME = ZC_DET_TIME; | |||
C4_SET.Bits.C4_AUTO_CAL_TIME = AUTO_CAL_TIME; | |||
DRV_write(DRV_CTRL_4, (uint8_t) C4_SET.Byte); | |||
DRV_write(DRV_LIB_SELECTION,LIB_SELECTION); | |||
//start autocalibration | |||
DRV_write(DRV_GO, 0x01); | |||
/* 0x00 sets DRV2605 out of standby and to use internal trigger | |||
* 0x01 sets DRV2605 out of standby and to use external trigger */ | |||
DRV_write(DRV_MODE,0x00); | |||
/* 0x06: LRA library */ | |||
DRV_write(DRV_WAVEFORM_SEQ_1, 0x01); | |||
/* 0xB9: LRA, 4x brake factor, medium gain, 7.5x back EMF | |||
* 0x39: ERM, 4x brake factor, medium gain, 1.365x back EMF */ | |||
/* TODO: setup auto-calibration as part of initiation */ | |||
} | |||
void DRV_pulse(uint8_t sequence) | |||
{ | |||
DRV_write(DRV_GO, 0x00); | |||
DRV_write(DRV_WAVEFORM_SEQ_1, sequence); | |||
DRV_write(DRV_GO, 0x01); | |||
} |
@ -0,0 +1,394 @@ | |||
/* Copyright 2018 ishtob | |||
* Driver for DRV2605L written for QMK | |||
* | |||
* This program is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 2 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#pragma once | |||
#include "i2c_master.h" | |||
/* Initialization settings | |||
* Feedback Control Settings */ | |||
#ifndef FB_ERM_LRA | |||
#define FB_ERM_LRA 1 /* For ERM:0 or LRA:1*/ | |||
#endif | |||
#ifndef FB_BRAKEFACTOR | |||
#define FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */ | |||
#endif | |||
#ifndef FB_LOOPGAIN | |||
#define FB_LOOPGAIN 1 /* For Low:0, Medium:1, High:2, Very High:3 */ | |||
#endif | |||
#ifndef RATED_VOLTAGE | |||
#define RATED_VOLTAGE 2 /* 2v as safe range in case device voltage is not set */ | |||
#ifndef V_PEAK | |||
#define V_PEAK 2.8 | |||
#endif | |||
#endif | |||
/* LRA specific settings */ | |||
#if FB_ERM_LRA == 1 | |||
#ifndef V_RMS | |||
#define V_RMS 2.0 | |||
#endif | |||
#ifndef V_PEAK | |||
#define V_PEAK 2.1 | |||
#endif | |||
#ifndef F_LRA | |||
#define F_LRA 205 | |||
#endif | |||
#endif | |||
/* Library Selection */ | |||
#ifndef LIB_SELECTION | |||
#if FB_ERM_LRA == 1 | |||
#define LIB_SELECTION 6 /* For Empty:0' TS2200 library A to D:1-5, LRA Library: 6 */ | |||
#else | |||
#define LIB_SELECTION 1 | |||
#endif | |||
#endif | |||
/* Control 1 register settings */ | |||
#ifndef DRIVE_TIME | |||
#define DRIVE_TIME 25 | |||
#endif | |||
#ifndef AC_COUPLE | |||
#define AC_COUPLE 0 | |||
#endif | |||
#ifndef STARTUP_BOOST | |||
#define STARTUP_BOOST 1 | |||
#endif | |||
/* Control 2 Settings */ | |||
#ifndef BIDIR_INPUT | |||
#define BIDIR_INPUT 1 | |||
#endif | |||
#ifndef BRAKE_STAB | |||
#define BRAKE_STAB 1 /* Loopgain is reduced when braking is almost complete to improve stability */ | |||
#endif | |||
#ifndef SAMPLE_TIME | |||
#define SAMPLE_TIME 3 | |||
#endif | |||
#ifndef BLANKING_TIME | |||
#define BLANKING_TIME 1 | |||
#endif | |||
#ifndef IDISS_TIME | |||
#define IDISS_TIME 1 | |||
#endif | |||
/* Control 3 settings */ | |||
#ifndef NG_THRESH | |||
#define NG_THRESH 2 | |||
#endif | |||
#ifndef ERM_OPEN_LOOP | |||
#define ERM_OPEN_LOOP 1 | |||
#endif | |||
#ifndef SUPPLY_COMP_DIS | |||
#define SUPPLY_COMP_DIS 0 | |||
#endif | |||
#ifndef DATA_FORMAT_RTO | |||
#define DATA_FORMAT_RTO 0 | |||
#endif | |||
#ifndef LRA_DRIVE_MODE | |||
#define LRA_DRIVE_MODE 0 | |||
#endif | |||
#ifndef N_PWM_ANALOG | |||
#define N_PWM_ANALOG 0 | |||
#endif | |||
#ifndef LRA_OPEN_LOOP | |||
#define LRA_OPEN_LOOP 0 | |||
#endif | |||
/* Control 4 settings */ | |||
#ifndef ZC_DET_TIME | |||
#define ZC_DET_TIME 0 | |||
#endif | |||
#ifndef AUTO_CAL_TIME | |||
#define AUTO_CAL_TIME 3 | |||
#endif | |||
/* register defines -------------------------------------------------------- */ | |||
#define DRV2605L_BASE_ADDRESS 0x5A /* DRV2605L Base address */ | |||
#define DRV_STATUS 0x00 | |||
#define DRV_MODE 0x01 | |||
#define DRV_RTP_INPUT 0x02 | |||
#define DRV_LIB_SELECTION 0x03 | |||
#define DRV_WAVEFORM_SEQ_1 0x04 | |||
#define DRV_WAVEFORM_SEQ_2 0x05 | |||
#define DRV_WAVEFORM_SEQ_3 0x06 | |||
#define DRV_WAVEFORM_SEQ_4 0x07 | |||
#define DRV_WAVEFORM_SEQ_5 0x08 | |||
#define DRV_WAVEFORM_SEQ_6 0x09 | |||
#define DRV_WAVEFORM_SEQ_7 0x0A | |||
#define DRV_WAVEFORM_SEQ_8 0x0B | |||
#define DRV_GO 0x0C | |||
#define DRV_OVERDRIVE_TIME_OFFSET 0x0D | |||
#define DRV_SUSTAIN_TIME_OFFSET_P 0x0E | |||
#define DRV_SUSTAIN_TIME_OFFSET_N 0x0F | |||
#define DRV_BRAKE_TIME_OFFSET 0x10 | |||
#define DRV_AUDIO_2_VIBE_CTRL 0x11 | |||
#define DRV_AUDIO_2_VIBE_MIN_IN 0x12 | |||
#define DRV_AUDIO_2_VIBE_MAX_IN 0x13 | |||
#define DRV_AUDIO_2_VIBE_MIN_OUTDRV 0x14 | |||
#define DRV_AUDIO_2_VIBE_MAX_OUTDRV 0x15 | |||
#define DRV_RATED_VOLT 0x16 | |||
#define DRV_OVERDRIVE_CLAMP_VOLT 0x17 | |||
#define DRV_AUTO_CALIB_COMP_RESULT 0x18 | |||
#define DRV_AUTO_CALIB_BEMF_RESULT 0x19 | |||
#define DRV_FEEDBACK_CTRL 0x1A | |||
#define DRV_CTRL_1 0x1B | |||
#define DRV_CTRL_2 0x1C | |||
#define DRV_CTRL_3 0x1D | |||
#define DRV_CTRL_4 0x1E | |||
#define DRV_CTRL_5 0x1F | |||
#define DRV_OPEN_LOOP_PERIOD 0x20 | |||
#define DRV_VBAT_VOLT_MONITOR 0x21 | |||
#define DRV_LRA_RESONANCE_PERIOD 0x22 | |||
void DRV_init(void); | |||
void DRV_write(const uint8_t drv_register, const uint8_t settings); | |||
uint8_t DRV_read(const uint8_t regaddress); | |||
void DRV_pulse(const uint8_t sequence); | |||
typedef enum DRV_EFFECT{ | |||
clear_sequence = 0, | |||
strong_click = 1, | |||
strong_click_60 = 2, | |||
strong_click_30 = 3, | |||
sharp_click = 4, | |||
sharp_click_60 = 5, | |||
sharp_click_30 = 6, | |||
soft_bump = 7, | |||
soft_bump_60 = 8, | |||
soft_bump_30 = 9, | |||
dbl_click = 10, | |||
dbl_click_60 = 11, | |||
trp_click = 12, | |||
soft_fuzz = 13, | |||
strong_buzz = 14, | |||
alert_750ms = 15, | |||
alert_1000ms = 16, | |||
strong_click1 = 17, | |||
strong_click2_80 = 18, | |||
strong_click3_60 = 19, | |||
strong_click4_30 = 20, | |||
medium_click1 = 21, | |||
medium_click2_80 = 22, | |||
medium_click3_60 = 23, | |||
sharp_tick1 = 24, | |||
sharp_tick2_80 = 25, | |||
sharp_tick3_60 = 26, | |||
sh_dblclick_str = 27, | |||
sh_dblclick_str_80 = 28, | |||
sh_dblclick_str_60 = 29, | |||
sh_dblclick_str_30 = 30, | |||
sh_dblclick_med = 31, | |||
sh_dblclick_med_80 = 32, | |||
sh_dblclick_med_60 = 33, | |||
sh_dblsharp_tick = 34, | |||
sh_dblsharp_tick_80 = 35, | |||
sh_dblsharp_tick_60 = 36, | |||
lg_dblclick_str = 37, | |||
lg_dblclick_str_80 = 38, | |||
lg_dblclick_str_60 = 39, | |||
lg_dblclick_str_30 = 40, | |||
lg_dblclick_med = 41, | |||
lg_dblclick_med_80 = 42, | |||
lg_dblclick_med_60 = 43, | |||
lg_dblsharp_tick = 44, | |||
lg_dblsharp_tick_80 = 45, | |||
lg_dblsharp_tick_60 = 46, | |||
buzz = 47, | |||
buzz_80 = 48, | |||
buzz_60 = 49, | |||
buzz_40 = 50, | |||
buzz_20 = 51, | |||
pulsing_strong = 52, | |||
pulsing_strong_80 = 53, | |||
pulsing_medium = 54, | |||
pulsing_medium_80 = 55, | |||
pulsing_sharp = 56, | |||
pulsing_sharp_80 = 57, | |||
transition_click = 58, | |||
transition_click_80 = 59, | |||
transition_click_60 = 60, | |||
transition_click_40 = 61, | |||
transition_click_20 = 62, | |||
transition_click_10 = 63, | |||
transition_hum = 64, | |||
transition_hum_80 = 65, | |||
transition_hum_60 = 66, | |||
transition_hum_40 = 67, | |||
transition_hum_20 = 68, | |||
transition_hum_10 = 69, | |||
transition_rampdown_long_smooth1 = 70, | |||
transition_rampdown_long_smooth2 = 71, | |||
transition_rampdown_med_smooth1 = 72, | |||
transition_rampdown_med_smooth2 = 73, | |||
transition_rampdown_short_smooth1 = 74, | |||
transition_rampdown_short_smooth2 = 75, | |||
transition_rampdown_long_sharp1 = 76, | |||
transition_rampdown_long_sharp2 = 77, | |||
transition_rampdown_med_sharp1 = 78, | |||
transition_rampdown_med_sharp2 = 79, | |||
transition_rampdown_short_sharp1 = 80, | |||
transition_rampdown_short_sharp2 = 81, | |||
transition_rampup_long_smooth1 = 82, | |||
transition_rampup_long_smooth2 = 83, | |||
transition_rampup_med_smooth1 = 84, | |||
transition_rampup_med_smooth2 = 85, | |||
transition_rampup_short_smooth1 = 86, | |||
transition_rampup_short_smooth2 = 87, | |||
transition_rampup_long_sharp1 = 88, | |||
transition_rampup_long_sharp2 = 89, | |||
transition_rampup_med_sharp1 = 90, | |||
transition_rampup_med_sharp2 = 91, | |||
transition_rampup_short_sharp1 = 92, | |||
transition_rampup_short_sharp2 = 93, | |||
transition_rampdown_long_smooth1_50 = 94, | |||
transition_rampdown_long_smooth2_50 = 95, | |||
transition_rampdown_med_smooth1_50 = 96, | |||
transition_rampdown_med_smooth2_50 = 97, | |||
transition_rampdown_short_smooth1_50 = 98, | |||
transition_rampdown_short_smooth2_50 = 99, | |||
transition_rampdown_long_sharp1_50 = 100, | |||
transition_rampdown_long_sharp2_50 = 101, | |||
transition_rampdown_med_sharp1_50 = 102, | |||
transition_rampdown_med_sharp2_50 = 103, | |||
transition_rampdown_short_sharp1_50 = 104, | |||
transition_rampdown_short_sharp2_50 = 105, | |||
transition_rampup_long_smooth1_50 = 106, | |||
transition_rampup_long_smooth2_50 = 107, | |||
transition_rampup_med_smooth1_50 = 108, | |||
transition_rampup_med_smooth2_50 = 109, | |||
transition_rampup_short_smooth1_50 = 110, | |||
transition_rampup_short_smooth2_50 = 111, | |||
transition_rampup_long_sharp1_50 = 112, | |||
transition_rampup_long_sharp2_50 = 113, | |||
transition_rampup_med_sharp1_50 = 114, | |||
transition_rampup_med_sharp2_50 = 115, | |||
transition_rampup_short_sharp1_50 = 116, | |||
transition_rampup_short_sharp2_50 = 117, | |||
long_buzz_for_programmatic_stopping = 118, | |||
smooth_hum1_50 = 119, | |||
smooth_hum2_40 = 120, | |||
smooth_hum3_30 = 121, | |||
smooth_hum4_20 = 122, | |||
smooth_hum5_10 = 123, | |||
} DRV_EFFECT; | |||
/* Register bit array unions */ | |||
typedef union DRVREG_STATUS { /* register 0x00 */ | |||
uint8_t Byte; | |||
struct { | |||
uint8_t OC_DETECT :1; /* set to 1 when overcurrent event is detected */ | |||
uint8_t OVER_TEMP :1; /* set to 1 when device exceeds temp threshold */ | |||
uint8_t FB_STS :1; /* set to 1 when feedback controller has timed out */ | |||
/* auto-calibration routine and diagnostic result | |||
* result | auto-calibation | diagnostic | | |||
* 0 | passed | actuator func normal | | |||
* 1 | failed | actuator func fault* | | |||
* * actuator is not present or is shorted, timing out, or giving out–of-range back-EMF */ | |||
uint8_t DIAG_RESULT :1; | |||
uint8_t :1; | |||
uint8_t DEVICE_ID :3; /* Device IDs 3: DRV2605 4: DRV2604 5: DRV2604L 6: DRV2605L */ | |||
} Bits; | |||
} DRVREG_STATUS; | |||
typedef union DRVREG_MODE { /* register 0x01 */ | |||
uint8_t Byte; | |||
struct { | |||
uint8_t MODE :3; /* Mode setting */ | |||
uint8_t :3; | |||
uint8_t STANDBY :1; /* 0:standby 1:ready */ | |||
} Bits; | |||
} DRVREG_MODE; | |||
typedef union DRVREG_WAIT { | |||
uint8_t Byte; | |||
struct { | |||
uint8_t WAIT_MODE :1; /* Set to 1 to interpret as wait for next 7 bits x10ms */ | |||
uint8_t WAIT_TIME :7; | |||
} Bits; | |||
} DRVREG_WAIT; | |||
typedef union DRVREG_FBR{ /* register 0x1A */ | |||
uint8_t Byte; | |||
struct { | |||
uint8_t BEMF_GAIN :2; | |||
uint8_t LOOP_GAIN :2; | |||
uint8_t BRAKE_FACTOR :3; | |||
uint8_t ERM_LRA :1; | |||
} Bits; | |||
} DRVREG_FBR; | |||
typedef union DRVREG_CTRL1{ /* register 0x1B */ | |||
uint8_t Byte; | |||
struct { | |||
uint8_t C1_DRIVE_TIME :5; | |||
uint8_t C1_AC_COUPLE :1; | |||
uint8_t :1; | |||
uint8_t C1_STARTUP_BOOST :1; | |||
} Bits; | |||
} DRVREG_CTRL1; | |||
typedef union DRVREG_CTRL2{ /* register 0x1C */ | |||
uint8_t Byte; | |||
struct { | |||
uint8_t C2_IDISS_TIME :2; | |||
uint8_t C2_BLANKING_TIME :2; | |||
uint8_t C2_SAMPLE_TIME :2; | |||
uint8_t C2_BRAKE_STAB :1; | |||
uint8_t C2_BIDIR_INPUT :1; | |||
} Bits; | |||
} DRVREG_CTRL2; | |||
typedef union DRVREG_CTRL3{ /* register 0x1D */ | |||
uint8_t Byte; | |||
struct { | |||
uint8_t C3_LRA_OPEN_LOOP :1; | |||
uint8_t C3_N_PWM_ANALOG :1; | |||
uint8_t C3_LRA_DRIVE_MODE :1; | |||
uint8_t C3_DATA_FORMAT_RTO :1; | |||
uint8_t C3_SUPPLY_COMP_DIS :1; | |||
uint8_t C3_ERM_OPEN_LOOP :1; | |||
uint8_t C3_NG_THRESH :2; | |||
} Bits; | |||
} DRVREG_CTRL3; | |||
typedef union DRVREG_CTRL4{ /* register 0x1E */ | |||
uint8_t Byte; | |||
struct { | |||
uint8_t C4_OTP_PROGRAM :1; | |||
uint8_t :1; | |||
uint8_t C4_OTP_STATUS :1; | |||
uint8_t :1; | |||
uint8_t C4_AUTO_CAL_TIME :2; | |||
uint8_t C4_ZC_DET_TIME :2; | |||
} Bits; | |||
} DRVREG_CTRL4; | |||
typedef union DRVREG_CTRL5{ /* register 0x1F */ | |||
uint8_t Byte; | |||
struct { | |||
uint8_t C5_IDISS_TIME :2; | |||
uint8_t C5_BLANKING_TIME :2; | |||
uint8_t C5_PLAYBACK_INTERVAL :1; | |||
uint8_t C5_LRA_AUTO_OPEN_LOOP :1; | |||
uint8_t C5_AUTO_OL_CNT :2; | |||
} Bits; | |||
} DRVREG_CTRL5; |
@ -0,0 +1,102 @@ | |||
/* Copyright 2018 Jason Williams (Wilba) | |||
* | |||
* 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 "is31fl3218.h" | |||
#include "i2c_master.h" | |||
// This is the full 8-bit address | |||
#define ISSI_ADDRESS 0b10101000 | |||
// These are the register addresses | |||
#define ISSI_REG_SHUTDOWN 0x00 | |||
#define ISSI_REG_PWM 0x01 | |||
#define ISSI_REG_CONTROL 0x13 | |||
#define ISSI_REG_UPDATE 0x16 | |||
#define ISSI_REG_RESET 0x17 | |||
// Default timeout if no I2C response | |||
#define ISSI_TIMEOUT 100 | |||
// Reusable buffer for transfers | |||
uint8_t g_twi_transfer_buffer[20]; | |||
// IS31FL3218 has 18 PWM outputs and a fixed I2C address, so no chaining. | |||
// If used as RGB LED driver, LEDs are assigned RGB,RGB,RGB,RGB,RGB,RGB | |||
uint8_t g_pwm_buffer[18]; | |||
bool g_pwm_buffer_update_required = false; | |||
void IS31FL3218_write_register( uint8_t reg, uint8_t data ) | |||
{ | |||
g_twi_transfer_buffer[0] = reg; | |||
g_twi_transfer_buffer[1] = data; | |||
i2c_transmit( ISSI_ADDRESS, g_twi_transfer_buffer, 2, ISSI_TIMEOUT); | |||
} | |||
void IS31FL3218_write_pwm_buffer( uint8_t *pwm_buffer ) | |||
{ | |||
g_twi_transfer_buffer[0] = ISSI_REG_PWM; | |||
for ( int i=0; i<18; i++ ) { | |||
g_twi_transfer_buffer[1+i] = pwm_buffer[i]; | |||
} | |||
i2c_transmit( ISSI_ADDRESS, g_twi_transfer_buffer, 19, ISSI_TIMEOUT); | |||
} | |||
void IS31FL3218_init(void) | |||
{ | |||
// In case we ever want to reinitialize (?) | |||
IS31FL3218_write_register( ISSI_REG_RESET, 0x00 ); | |||
// Turn off software shutdown | |||
IS31FL3218_write_register( ISSI_REG_SHUTDOWN, 0x01 ); | |||
// Set all PWM values to zero | |||
for ( uint8_t i = 0; i < 18; i++ ) { | |||
IS31FL3218_write_register( ISSI_REG_PWM+i, 0x00 ); | |||
} | |||
// Enable all channels | |||
for ( uint8_t i = 0; i < 3; i++ ) { | |||
IS31FL3218_write_register( ISSI_REG_CONTROL+i, 0b00111111 ); | |||
} | |||
// Load PWM registers and LED Control register data | |||
IS31FL3218_write_register( ISSI_REG_UPDATE, 0x01 ); | |||
} | |||
void IS31FL3218_set_color( int index, uint8_t red, uint8_t green, uint8_t blue ) | |||
{ | |||
g_pwm_buffer[index * 3 + 0] = red; | |||
g_pwm_buffer[index * 3 + 1] = green; | |||
g_pwm_buffer[index * 3 + 2] = blue; | |||
g_pwm_buffer_update_required = true; | |||
} | |||
void IS31FL3218_set_color_all( uint8_t red, uint8_t green, uint8_t blue ) | |||
{ | |||
for ( int i = 0; i < 6; i++ ) { | |||
IS31FL3218_set_color( i, red, green, blue ); | |||
} | |||
} | |||
void IS31FL3218_update_pwm_buffers(void) | |||
{ | |||
if ( g_pwm_buffer_update_required ) { | |||
IS31FL3218_write_pwm_buffer( g_pwm_buffer ); | |||
// Load PWM registers and LED Control register data | |||
IS31FL3218_write_register( ISSI_REG_UPDATE, 0x01 ); | |||
} | |||
g_pwm_buffer_update_required = false; | |||
} |
@ -0,0 +1,24 @@ | |||
/* Copyright 2018 Jason Williams (Wilba) | |||
* | |||
* This program is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 2 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#pragma once | |||
#include <stdint.h> | |||
#include <stdbool.h> | |||
void IS31FL3218_init(void); | |||
void IS31FL3218_set_color( int index, uint8_t red, uint8_t green, uint8_t blue ); | |||
void IS31FL3218_set_color_all( uint8_t red, uint8_t green, uint8_t blue ); | |||
void IS31FL3218_update_pwm_buffers(void); |
@ -0,0 +1,306 @@ | |||
/* Copyright 2018 Jason Williams (Wilba) | |||
* | |||
* 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/>. | |||
*/ | |||
#ifdef __AVR__ | |||
#include <avr/interrupt.h> | |||
#include <avr/io.h> | |||
#include <util/delay.h> | |||
#else | |||
#include "wait.h" | |||
#endif | |||
#include "is31fl3736.h" | |||
#include <string.h> | |||
#include "i2c_master.h" | |||
#include "progmem.h" | |||
// This is a 7-bit address, that gets left-shifted and bit 0 | |||
// set to 0 for write, 1 for read (as per I2C protocol) | |||
// The address will vary depending on your wiring: | |||
// 00 <-> GND | |||
// 01 <-> SCL | |||
// 10 <-> SDA | |||
// 11 <-> VCC | |||
// ADDR1 represents A1:A0 of the 7-bit address. | |||
// ADDR2 represents A3:A2 of the 7-bit address. | |||
// The result is: 0b101(ADDR2)(ADDR1) | |||
#define ISSI_ADDR_DEFAULT 0x50 | |||
#define ISSI_COMMANDREGISTER 0xFD | |||
#define ISSI_COMMANDREGISTER_WRITELOCK 0xFE | |||
#define ISSI_INTERRUPTMASKREGISTER 0xF0 | |||
#define ISSI_INTERRUPTSTATUSREGISTER 0xF1 | |||
#define ISSI_PAGE_LEDCONTROL 0x00 //PG0 | |||
#define ISSI_PAGE_PWM 0x01 //PG1 | |||
#define ISSI_PAGE_AUTOBREATH 0x02 //PG2 | |||
#define ISSI_PAGE_FUNCTION 0x03 //PG3 | |||
#define ISSI_REG_CONFIGURATION 0x00 //PG3 | |||
#define ISSI_REG_GLOBALCURRENT 0x01 //PG3 | |||
#define ISSI_REG_RESET 0x11// PG3 | |||
#define ISSI_REG_SWPULLUP 0x0F //PG3 | |||
#define ISSI_REG_CSPULLUP 0x10 //PG3 | |||
#ifndef ISSI_TIMEOUT | |||
#define ISSI_TIMEOUT 100 | |||
#endif | |||
#ifndef ISSI_PERSISTENCE | |||
#define ISSI_PERSISTENCE 0 | |||
#endif | |||
// Transfer buffer for TWITransmitData() | |||
uint8_t g_twi_transfer_buffer[20]; | |||
// These buffers match the IS31FL3736 PWM registers. | |||
// The control buffers match the PG0 LED On/Off registers. | |||
// Storing them like this is optimal for I2C transfers to the registers. | |||
// We could optimize this and take out the unused registers from these | |||
// buffers and the transfers in IS31FL3736_write_pwm_buffer() but it's | |||
// probably not worth the extra complexity. | |||
uint8_t g_pwm_buffer[DRIVER_COUNT][192]; | |||
bool g_pwm_buffer_update_required = false; | |||
uint8_t g_led_control_registers[DRIVER_COUNT][24] = { { 0 }, { 0 } }; | |||
bool g_led_control_registers_update_required = false; | |||
void IS31FL3736_write_register( uint8_t addr, uint8_t reg, uint8_t data ) | |||
{ | |||
g_twi_transfer_buffer[0] = reg; | |||
g_twi_transfer_buffer[1] = data; | |||
#if ISSI_PERSISTENCE > 0 | |||
for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) { | |||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT) == 0) | |||
break; | |||
} | |||
#else | |||
i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT); | |||
#endif | |||
} | |||
void IS31FL3736_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer ) | |||
{ | |||
// assumes PG1 is already selected | |||
// transmit PWM registers in 12 transfers of 16 bytes | |||
// g_twi_transfer_buffer[] is 20 bytes | |||
// iterate over the pwm_buffer contents at 16 byte intervals | |||
for ( int i = 0; i < 192; i += 16 ) { | |||
g_twi_transfer_buffer[0] = i; | |||
// copy the data from i to i+15 | |||
// device will auto-increment register for data after the first byte | |||
// thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer | |||
for ( int j = 0; j < 16; j++ ) { | |||
g_twi_transfer_buffer[1 + j] = pwm_buffer[i + j]; | |||
} | |||
#if ISSI_PERSISTENCE > 0 | |||
for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) { | |||
if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT) == 0) | |||
break; | |||
} | |||
#else | |||
i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT); | |||
#endif | |||
} | |||
} | |||
void IS31FL3736_init( uint8_t addr ) | |||
{ | |||
// In order to avoid the LEDs being driven with garbage data | |||
// in the LED driver's PWM registers, shutdown is enabled last. | |||
// Set up the mode and other settings, clear the PWM registers, | |||
// then disable software shutdown. | |||
// Unlock the command register. | |||
IS31FL3736_write_register( addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 ); | |||
// Select PG0 | |||
IS31FL3736_write_register( addr, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL ); | |||
// Turn off all LEDs. | |||
for ( int i = 0x00; i <= 0x17; i++ ) | |||
{ | |||
IS31FL3736_write_register( addr, i, 0x00 ); | |||
} | |||
// Unlock the command register. | |||
IS31FL3736_write_register( addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 ); | |||
// Select PG1 | |||
IS31FL3736_write_register( addr, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM ); | |||
// Set PWM on all LEDs to 0 | |||
// No need to setup Breath registers to PWM as that is the default. | |||
for ( int i = 0x00; i <= 0xBF; i++ ) | |||
{ | |||
IS31FL3736_write_register( addr, i, 0x00 ); | |||
} | |||
// Unlock the command register. | |||
IS31FL3736_write_register( addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 ); | |||
// Select PG3 | |||
IS31FL3736_write_register( addr, ISSI_COMMANDREGISTER, ISSI_PAGE_FUNCTION ); | |||
// Set global current to maximum. | |||
IS31FL3736_write_register( addr, ISSI_REG_GLOBALCURRENT, 0xFF ); | |||
// Disable software shutdown. | |||
IS31FL3736_write_register( addr, ISSI_REG_CONFIGURATION, 0x01 ); | |||
// Wait 10ms to ensure the device has woken up. | |||
#ifdef __AVR__ | |||
_delay_ms( 10 ); | |||
#else | |||
wait_ms(10); | |||
#endif | |||
} | |||
void IS31FL3736_set_color( int index, uint8_t red, uint8_t green, uint8_t blue ) | |||
{ | |||
if ( index >= 0 && index < DRIVER_LED_TOTAL ) { | |||
is31_led led = g_is31_leds[index]; | |||
g_pwm_buffer[led.driver][led.r] = red; | |||
g_pwm_buffer[led.driver][led.g] = green; | |||
g_pwm_buffer[led.driver][led.b] = blue; | |||
g_pwm_buffer_update_required = true; | |||
} | |||
} | |||
void IS31FL3736_set_color_all( uint8_t red, uint8_t green, uint8_t blue ) | |||
{ | |||
for ( int i = 0; i < DRIVER_LED_TOTAL; i++ ) | |||
{ | |||
IS31FL3736_set_color( i, red, green, blue ); | |||
} | |||
} | |||
void IS31FL3736_set_led_control_register( uint8_t index, bool red, bool green, bool blue ) | |||
{ | |||
is31_led led = g_is31_leds[index]; | |||
// IS31FL3733 | |||
// The PWM register for a matrix position (0x00 to 0xBF) can be | |||
// divided by 8 to get the LED control register (0x00 to 0x17), | |||
// then mod 8 to get the bit position within that register. | |||
// IS31FL3736 | |||
// The PWM register for a matrix position (0x00 to 0xBF) is interleaved, so: | |||
// A1=0x00 A2=0x02 A3=0x04 A4=0x06 A5=0x08 A6=0x0A A7=0x0C A8=0x0E | |||
// B1=0x10 B2=0x12 B3=0x14 | |||
// But also, the LED control registers (0x00 to 0x17) are also interleaved, so: | |||
// A1-A4=0x00 A5-A8=0x01 | |||
// So, the same math applies. | |||
uint8_t control_register_r = led.r / 8; | |||
uint8_t control_register_g = led.g / 8; | |||
uint8_t control_register_b = led.b / 8; | |||
uint8_t bit_r = led.r % 8; | |||
uint8_t bit_g = led.g % 8; | |||
uint8_t bit_b = led.b % 8; | |||
if ( red ) { | |||
g_led_control_registers[led.driver][control_register_r] |= (1 << bit_r); | |||
} else { | |||
g_led_control_registers[led.driver][control_register_r] &= ~(1 << bit_r); | |||
} | |||
if ( green ) { | |||
g_led_control_registers[led.driver][control_register_g] |= (1 << bit_g); | |||
} else { | |||
g_led_control_registers[led.driver][control_register_g] &= ~(1 << bit_g); | |||
} | |||
if ( blue ) { | |||
g_led_control_registers[led.driver][control_register_b] |= (1 << bit_b); | |||
} else { | |||
g_led_control_registers[led.driver][control_register_b] &= ~(1 << bit_b); | |||
} | |||
g_led_control_registers_update_required = true; | |||
} | |||
void IS31FL3736_mono_set_brightness( int index, uint8_t value ) | |||
{ | |||
if ( index >= 0 && index < 96 ) { | |||
// Index in range 0..95 -> A1..A8, B1..B8, etc. | |||
// Map index 0..95 to registers 0x00..0xBE (interleaved) | |||
uint8_t pwm_register = index * 2; | |||
g_pwm_buffer[0][pwm_register] = value; | |||
g_pwm_buffer_update_required = true; | |||
} | |||
} | |||
void IS31FL3736_mono_set_brightness_all( uint8_t value ) | |||
{ | |||
for ( int i = 0; i < 96; i++ ) | |||
{ | |||
IS31FL3736_mono_set_brightness( i, value ); | |||
} | |||
} | |||
void IS31FL3736_mono_set_led_control_register( uint8_t index, bool enabled ) | |||
{ | |||
// Index in range 0..95 -> A1..A8, B1..B8, etc. | |||
// Map index 0..95 to registers 0x00..0xBE (interleaved) | |||
uint8_t pwm_register = index * 2; | |||
// Map register 0x00..0xBE (interleaved) into control register and bit | |||
uint8_t control_register = pwm_register / 8; | |||
uint8_t bit = pwm_register % 8; | |||
if ( enabled ) { | |||
g_led_control_registers[0][control_register] |= (1 << bit); | |||
} else { | |||
g_led_control_registers[0][control_register] &= ~(1 << bit); | |||
} | |||
g_led_control_registers_update_required = true; | |||
} | |||
void IS31FL3736_update_pwm_buffers( uint8_t addr1, uint8_t addr2 ) | |||
{ | |||
if ( g_pwm_buffer_update_required ) | |||
{ | |||
// Firstly we need to unlock the command register and select PG1 | |||
IS31FL3736_write_register( addr1, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 ); | |||
IS31FL3736_write_register( addr1, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM ); | |||
IS31FL3736_write_pwm_buffer( addr1, g_pwm_buffer[0] ); | |||
//IS31FL3736_write_pwm_buffer( addr2, g_pwm_buffer[1] ); | |||
} | |||
g_pwm_buffer_update_required = false; | |||
} | |||
void IS31FL3736_update_led_control_registers( uint8_t addr1, uint8_t addr2 ) | |||
{ | |||
if ( g_led_control_registers_update_required ) | |||
{ | |||
// Firstly we need to unlock the command register and select PG0 | |||
IS31FL3736_write_register( addr1, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 ); | |||
IS31FL3736_write_register( addr1, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL ); | |||
for ( int i=0; i<24; i++ ) | |||
{ | |||
IS31FL3736_write_register(addr1, i, g_led_control_registers[0][i] ); | |||
//IS31FL3736_write_register(addr2, i, g_led_control_registers[1][i] ); | |||
} | |||
} | |||
} | |||
@ -0,0 +1,172 @@ | |||
/* Copyright 2018 Jason Williams (Wilba) | |||
* | |||
* This program is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 2 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#pragma once | |||
#include <stdint.h> | |||
#include <stdbool.h> | |||
// Simple interface option. | |||
// If these aren't defined, just define them to make it compile | |||
#ifndef DRIVER_COUNT | |||
#define DRIVER_COUNT 2 | |||
#endif | |||
#ifndef DRIVER_LED_TOTAL | |||
#define DRIVER_LED_TOTAL 96 | |||
#endif | |||
typedef struct is31_led { | |||
uint8_t driver:2; | |||
uint8_t r; | |||
uint8_t g; | |||
uint8_t b; | |||
} __attribute__((packed)) is31_led; | |||
extern const is31_led g_is31_leds[DRIVER_LED_TOTAL]; | |||
void IS31FL3736_init( uint8_t addr ); | |||
void IS31FL3736_write_register( uint8_t addr, uint8_t reg, uint8_t data ); | |||
void IS31FL3736_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer ); | |||
void IS31FL3736_set_color( int index, uint8_t red, uint8_t green, uint8_t blue ); | |||
void IS31FL3736_set_color_all( uint8_t red, uint8_t green, uint8_t blue ); | |||
void IS31FL3736_set_led_control_register( uint8_t index, bool red, bool green, bool blue ); | |||
void IS31FL3736_mono_set_brightness( int index, uint8_t value ); | |||
void IS31FL3736_mono_set_brightness_all( uint8_t value ); | |||
void IS31FL3736_mono_set_led_control_register( uint8_t index, bool enabled ); | |||
// This should not be called from an interrupt | |||
// (eg. from a timer interrupt). | |||
// Call this while idle (in between matrix scans). | |||
// If the buffer is dirty, it will update the driver with the buffer. | |||
void IS31FL3736_update_pwm_buffers( uint8_t addr1, uint8_t addr2 ); | |||
void IS31FL3736_update_led_control_registers( uint8_t addr1, uint8_t addr2 ); | |||
#define A_1 0x00 | |||
#define A_2 0x02 | |||
#define A_3 0x04 | |||
#define A_4 0x06 | |||
#define A_5 0x08 | |||
#define A_6 0x0A | |||
#define A_7 0x0C | |||
#define A_8 0x0E | |||
#define B_1 0x10 | |||
#define B_2 0x12 | |||
#define B_3 0x14 | |||
#define B_4 0x16 | |||
#define B_5 0x18 | |||
#define B_6 0x1A | |||
#define B_7 0x1C | |||
#define B_8 0x1E | |||
#define C_1 0x20 | |||
#define C_2 0x22 | |||
#define C_3 0x24 | |||
#define C_4 0x26 | |||
#define C_5 0x28 | |||
#define C_6 0x2A | |||
#define C_7 0x2C | |||
#define C_8 0x2E | |||
#define D_1 0x30 | |||
#define D_2 0x32 | |||
#define D_3 0x34 | |||
#define D_4 0x36 | |||
#define D_5 0x38 | |||
#define D_6 0x3A | |||
#define D_7 0x3C | |||
#define D_8 0x3E | |||
#define E_1 0x40 | |||
#define E_2 0x42 | |||
#define E_3 0x44 | |||
#define E_4 0x46 | |||
#define E_5 0x48 | |||
#define E_6 0x4A | |||
#define E_7 0x4C | |||
#define E_8 0x4E | |||
#define F_1 0x50 | |||
#define F_2 0x52 | |||
#define F_3 0x54 | |||
#define F_4 0x56 | |||
#define F_5 0x58 | |||
#define F_6 0x5A | |||
#define F_7 0x5C | |||
#define F_8 0x5E | |||
#define G_1 0x60 | |||
#define G_2 0x62 | |||
#define G_3 0x64 | |||
#define G_4 0x66 | |||
#define G_5 0x68 | |||
#define G_6 0x6A | |||
#define G_7 0x6C | |||
#define G_8 0x6E | |||
#define H_1 0x70 | |||
#define H_2 0x72 | |||
#define H_3 0x74 | |||
#define H_4 0x76 | |||
#define H_5 0x78 | |||
#define H_6 0x7A | |||
#define H_7 0x7C | |||
#define H_8 0x7E | |||
#define I_1 0x80 | |||
#define I_2 0x82 | |||
#define I_3 0x84 | |||
#define I_4 0x86 | |||
#define I_5 0x88 | |||
#define I_6 0x8A | |||
#define I_7 0x8C | |||
#define I_8 0x8E | |||
#define J_1 0x90 | |||
#define J_2 0x92 | |||
#define J_3 0x94 | |||
#define J_4 0x96 | |||
#define J_5 0x98 | |||
#define J_6 0x9A | |||
#define J_7 0x9C | |||
#define J_8 0x9E | |||
#define K_1 0xA0 | |||
#define K_2 0xA2 | |||
#define K_3 0xA4 | |||
#define K_4 0xA6 | |||
#define K_5 0xA8 | |||
#define K_6 0xAA | |||
#define K_7 0xAC | |||
#define K_8 0xAE | |||
#define L_1 0xB0 | |||
#define L_2 0xB2 | |||
#define L_3 0xB4 | |||
#define L_4 0xB6 | |||
#define L_5 0xB8 | |||
#define L_6 0xBA | |||
#define L_7 0xBC | |||
#define L_8 0xBE | |||
@ -0,0 +1,691 @@ | |||
/* Jim Lindblom @ SparkFun Electronics | |||
* October 26, 2014 | |||
* https://github.com/sparkfun/Micro_OLED_Breakout/tree/master/Firmware/Arduino/libraries/SFE_MicroOLED | |||
* | |||
* Modified by: | |||
* Emil Varughese @ Edwin Robotics Pvt. Ltd. | |||
* July 27, 2015 | |||
* https://github.com/emil01/SparkFun_Micro_OLED_Arduino_Library/ | |||
* | |||
* This code was heavily based around the MicroView library, written by GeekAmmo | |||
* (https://github.com/geekammo/MicroView-Arduino-Library). | |||
* | |||
* Adapted for QMK by: | |||
* Jack Humbert <jack.humb@gmail.com> | |||
* October 11, 2018 | |||
* | |||
* This program is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include "micro_oled.h" | |||
#include <stdlib.h> | |||
#include "util/font5x7.h" | |||
#include "util/font8x16.h" | |||
#include "string.h" | |||
#define TOTALFONTS 2 | |||
const unsigned char * fonts_pointer[]= { font5x7, font8x16 }; | |||
uint8_t foreColor,drawMode,fontWidth, fontHeight, fontType, fontStartChar, fontTotalChar, cursorX, cursorY; | |||
uint16_t fontMapWidth; | |||
#define _BV(x) (1 << (x)) | |||
#define swap(a, b) { uint8_t t = a; a = b; b = t; } | |||
uint8_t micro_oled_transfer_buffer[20]; | |||
static uint8_t micro_oled_screen_current[LCDWIDTH*LCDWIDTH/8] = { 0 }; | |||
/* LCD Memory organised in 64 horizontal pixel and 6 rows of byte | |||
B B .............B ----- | |||
y y .............y \ | |||
t t .............t \ | |||
e e .............e \ | |||
0 1 .............63 \ | |||
\ | |||
D0 D0.............D0 \ | |||
D1 D1.............D1 / ROW 0 | |||
D2 D2.............D2 / | |||
D3 D3.............D3 / | |||
D4 D4.............D4 / | |||
D5 D5.............D5 / | |||
D6 D6.............D6 / | |||
D7 D7.............D7 ---- | |||
*/ | |||
#if LCDWIDTH == 64 | |||
#if LCDWIDTH == 48 | |||
static uint8_t micro_oled_screen_buffer[] = { | |||
// QMK Logo - generated at http://www.majer.ch/lcd/adf_bitmap.php | |||
//64x48 image | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00, | |||
0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00, | |||
0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x60, 0x60, | |||
0xF8, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFE, | |||
0xFE, 0xF8, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x8C, 0x8C, 0x8C, 0x8C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |||
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, | |||
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8C, 0x8C, 0x8C, 0x8C, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF8, 0xF1, 0xE3, 0xE7, 0xCF, | |||
0xCF, 0xCF, 0xCF, 0x00, 0x00, 0xCF, 0xCF, 0xCF, 0xC7, 0xE7, | |||
0xE3, 0xF1, 0xF8, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |||
0x31, 0x31, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, | |||
0x06, 0x06, 0x1F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |||
0xFF, 0x7F, 0x7F, 0x1F, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, | |||
0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, | |||
0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00 | |||
}; | |||
#endif | |||
#elif LCDWIDTH == 128 | |||
#if LCDHEIGHT == 32 | |||
static uint8_t micro_oled_screen_buffer[LCDWIDTH*LCDWIDTH/8] = { | |||
//128x32 qmk image | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x80, 0xC0, 0xE0, 0xE0, 0xFC, 0xFC, 0xE0, 0xFC, 0xFC, | |||
0xE0, 0xF0, 0xFC, 0xE0, 0xE0, 0xFC, 0xE0, 0xE0, 0xFC, 0xFC, | |||
0xE0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0xF0, 0x10, 0x10, 0x30, 0xE0, 0x00, 0x00, | |||
0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, | |||
0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x80, | |||
0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, | |||
0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, | |||
0x80, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xB2, 0xB2, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x03, 0xFF, 0xFF, 0xFF, 0x03, | |||
0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x03, 0xFF, 0xFF, 0xFF, | |||
0xFF, 0xB7, 0xB2, 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x1F, 0x02, 0x02, 0x03, 0x01, 0x00, 0x06, 0x1F, 0x10, | |||
0x10, 0x10, 0x1F, 0x06, 0x00, 0x03, 0x1E, 0x18, 0x0F, 0x01, | |||
0x0F, 0x18, 0x1E, 0x01, 0x00, 0x0F, 0x1F, 0x12, 0x02, 0x12, | |||
0x13, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x0E, 0x1F, 0x12, | |||
0x02, 0x12, 0x13, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x10, 0x1F, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x48, 0x4D, 0x4D, 0xFF, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFE, 0xF8, 0xF9, 0xF3, 0xF3, 0xC0, 0x80, 0xF3, | |||
0xF3, 0xF3, 0xF9, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, | |||
0x4D, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0xFE, 0x20, 0x10, 0x10, 0xE0, 0xC0, 0x00, 0x70, 0xC0, | |||
0x00, 0x80, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x0C, | |||
0x04, 0x04, 0x04, 0x04, 0x1C, 0xF0, 0x00, 0x00, 0xFC, 0x0C, | |||
0x38, 0xE0, 0x00, 0x00, 0xC0, 0x38, 0x0C, 0xFC, 0x00, 0x00, | |||
0xFC, 0xFC, 0x60, 0x90, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x07, 0x3F, | |||
0x3F, 0x07, 0x3F, 0x3F, 0x07, 0x0F, 0x3F, 0x07, 0x07, 0x3F, | |||
0x07, 0x07, 0x3F, 0x3F, 0x07, 0x07, 0x03, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, | |||
0x06, 0x04, 0x04, 0x07, 0x01, 0x00, 0x00, 0x13, 0x1E, 0x03, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x04, 0x04, | |||
0x04, 0x04, 0x07, 0x0D, 0x08, 0x00, 0x07, 0x00, 0x00, 0x01, | |||
0x07, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x07, | |||
0x00, 0x01, 0x03, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00 | |||
}; | |||
#elif LCDHEIGHT == 64 | |||
static uint8_t micro_oled_screen_buffer[LCDWIDTH*LCDWIDTH/8] = { | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, | |||
0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, | |||
0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0xC0, 0xC0, 0xC0, 0xC0, 0xF8, 0xFC, 0xFC, 0xFE, 0xFE, 0xFF, | |||
0x7F, 0x7E, 0xFE, 0xFF, 0xFF, 0xFE, 0xFE, 0x7F, 0x7F, 0xFE, | |||
0xFE, 0xFF, 0xFF, 0xFE, 0x7E, 0x7F, 0xFF, 0xFE, 0xFE, 0xFC, | |||
0xFC, 0xF8, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x88, 0x88, 0x88, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |||
0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xDD, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x99, 0x99, 0x99, 0x99, 0xFF, 0xFF, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFE, 0xF8, 0xF0, 0xF3, 0xF3, 0xE7, 0xE7, 0x00, | |||
0x00, 0xE7, 0xE7, 0xF3, 0xF3, 0xF0, 0xF8, 0xFE, 0xFF, 0xFF, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0x99, 0x99, 0x99, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x0F, 0x1F, 0x3F, | |||
0x3F, 0x3F, 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF, 0x3F, 0x3F, | |||
0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF, | |||
0x3F, 0x3F, 0x3F, 0x1F, 0x0F, 0x01, 0x01, 0x01, 0x01, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, | |||
0x80, 0x03, 0x03, 0x00, 0x00, 0x01, 0x03, 0x00, 0x80, 0x01, | |||
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0xFF, 0x11, 0x11, 0x11, 0x0E, 0x00, 0x70, | |||
0x88, 0x04, 0x04, 0x04, 0xF8, 0x00, 0x00, 0x3C, 0xE0, 0xC0, | |||
0x38, 0x1C, 0xE0, 0x80, 0x70, 0x0C, 0x00, 0xF8, 0xAC, 0x24, | |||
0x24, 0x3C, 0x30, 0x00, 0x00, 0xFC, 0x0C, 0x04, 0x00, 0xF8, | |||
0xAC, 0x24, 0x24, 0x2C, 0x30, 0x00, 0x70, 0xDC, 0x04, 0x04, | |||
0x88, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, | |||
0x8C, 0x04, 0x04, 0xF8, 0x00, 0x04, 0x3C, 0xE0, 0x80, 0xF0, | |||
0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x83, 0x01, 0x01, | |||
0x01, 0x81, 0xFE, 0x3C, 0x00, 0x00, 0xFF, 0x03, 0x0E, 0x70, | |||
0xC0, 0xE0, 0x38, 0x06, 0x03, 0xFF, 0x00, 0x00, 0xFF, 0x18, | |||
0x38, 0x66, 0xC3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, | |||
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, | |||
0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, | |||
0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, | |||
0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, | |||
0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, | |||
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, | |||
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | |||
}; | |||
//TODO: generate bitmap of QMK logo here | |||
#endif | |||
#else | |||
//catchall for custom screen szies | |||
static uint8_t micro_oled_screen_buffer[LCDWIDTH*LCDWIDTH/8] = {0}; | |||
#endif | |||
void micro_oled_init(void) { | |||
i2c_init(); | |||
i2c_start(I2C_ADDRESS_SA0_1); | |||
// Display Init sequence for 64x48 OLED module | |||
send_command(DISPLAYOFF); // 0xAE | |||
send_command(SETDISPLAYCLOCKDIV); // 0xD5 | |||
send_command(0x80); // the suggested ratio 0x80 | |||
send_command(SETMULTIPLEX); // 0xA8 | |||
send_command(LCDHEIGHT - 1); | |||
send_command(SETDISPLAYOFFSET); // 0xD3 | |||
send_command(0x00); // no offset | |||
send_command(SETSTARTLINE | 0x00); // line #0 | |||
send_command(CHARGEPUMP); // enable charge pump | |||
send_command(0x14); | |||
send_command(NORMALDISPLAY); // 0xA6 | |||
send_command(DISPLAYALLONRESUME); // 0xA4 | |||
//display at regular orientation | |||
send_command(SEGREMAP | 0x1); | |||
send_command(COMSCANDEC); | |||
//rotate display 180 | |||
#ifdef micro_oled_rotate_180 | |||
send_command(SEGREMAP); | |||
send_command(COMSCANINC); | |||
#endif | |||
send_command(MEMORYMODE); | |||
send_command(0x10); | |||
send_command(SETCOMPINS); // 0xDA | |||
if (LCDHEIGHT > 32) { | |||
send_command(0x12); | |||
} else { | |||
send_command(0x02); | |||
} | |||
send_command(SETCONTRAST); // 0x81 | |||
send_command(0x8F); | |||
send_command(SETPRECHARGE); // 0xd9 | |||
send_command(0xF1); | |||
send_command(SETVCOMDESELECT); // 0xDB | |||
send_command(0x40); | |||
send_command(DISPLAYON); //--turn on oled panel | |||
clear_screen(); // Erase hardware memory inside the OLED controller to avoid random data in memory. | |||
send_buffer(); | |||
} | |||
void send_command(uint8_t command) { | |||
micro_oled_transfer_buffer[0] = I2C_COMMAND; | |||
micro_oled_transfer_buffer[1] = command; | |||
i2c_transmit(I2C_ADDRESS_SA0_1 << 1, micro_oled_transfer_buffer, 2, 100); | |||
} | |||
void send_data(uint8_t data) { | |||
micro_oled_transfer_buffer[0] = I2C_DATA; | |||
micro_oled_transfer_buffer[1] = data; | |||
i2c_transmit(I2C_ADDRESS_SA0_1 << 1, micro_oled_transfer_buffer, 2, 100); | |||
} | |||
/** \brief Set SSD1306 page address. | |||
Send page address command and address to the SSD1306 OLED controller. | |||
*/ | |||
void set_page_address(uint8_t address) { | |||
address = (0xB0 | address); | |||
send_command(address); | |||
} | |||
/** \brief Set SSD1306 column address. | |||
Send column address command and address to the SSD1306 OLED controller. | |||
*/ | |||
void set_column_address(uint8_t address) { | |||
send_command( ( 0x10 | (address >> 4) ) + ((128 - LCDWIDTH) >> 8) ); | |||
send_command( 0x0F & address ); | |||
} | |||
/** \brief Clear SSD1306's memory. | |||
To clear GDRAM inside the LCD controller. | |||
*/ | |||
void clear_screen(void) { | |||
for (int i=0;i<8; i++) { | |||
set_page_address(i); | |||
set_column_address(0); | |||
for (int j=0; j<0x80; j++) { | |||
send_data(0); | |||
} | |||
} | |||
} | |||
/** \brief Clear SSD1306's memory. | |||
To clear GDRAM inside the LCD controller. | |||
*/ | |||
void clear_buffer(void) { | |||
//384 | |||
memset(micro_oled_screen_buffer, 0, LCDWIDTH*LCDWIDTH/8); | |||
} | |||
/** \brief Invert display. | |||
The PIXEL_ON color of the display will turn to PIXEL_OFF and the PIXEL_OFF will turn to PIXEL_ON. | |||
*/ | |||
void invert_screen(bool invert) { | |||
if (invert) { | |||
send_command(INVERTDISPLAY); | |||
} else { | |||
send_command(NORMALDISPLAY); | |||
} | |||
} | |||
/** \brief Set contrast. | |||
OLED contract value from 0 to 255. Note: Contrast level is not very obvious. | |||
*/ | |||
void set_contrast(uint8_t contrast) { | |||
send_command(SETCONTRAST); // 0x81 | |||
send_command(contrast); | |||
} | |||
/** \brief Transfer display buffer. | |||
Sends the updated buffer to the controller - the current status is checked before to save i2c exectution time | |||
*/ | |||
void send_buffer(void) { | |||
uint8_t i, j; | |||
uint8_t page_addr = 0xFF; | |||
for (i = 0; i < LCDHEIGHT/8; i++) { | |||
uint8_t col_addr = 0xFF; | |||
for (j = 0; j < LCDWIDTH; j++) { | |||
if (micro_oled_screen_buffer[i*LCDWIDTH+j] != micro_oled_screen_current[i*LCDWIDTH+j]) { | |||
if (page_addr != i) { | |||
set_page_address(i); | |||
} | |||
if (col_addr != j) { | |||
set_column_address(j); | |||
} | |||
send_data(micro_oled_screen_buffer[i*LCDWIDTH+j]); | |||
micro_oled_screen_current[i*LCDWIDTH+j] = micro_oled_screen_buffer[i*LCDWIDTH+j]; | |||
col_addr = j + 1; | |||
} | |||
} | |||
} | |||
} | |||
/** \brief Draw pixel with color and mode. | |||
Draw color pixel in the screen buffer's x,y position with NORM or XOR draw mode. | |||
*/ | |||
void draw_pixel(uint8_t x, uint8_t y, uint8_t color, uint8_t mode) { | |||
if ((x<0) || (x>=LCDWIDTH) || (y<0) || (y>=LCDHEIGHT)) | |||
return; | |||
if (mode == XOR) { | |||
if (color == PIXEL_ON) | |||
micro_oled_screen_buffer[x + (y/8)*LCDWIDTH] ^= _BV((y%8)); | |||
} else { | |||
if (color == PIXEL_ON) | |||
micro_oled_screen_buffer[x + (y/8)*LCDWIDTH] |= _BV((y%8)); | |||
else | |||
micro_oled_screen_buffer[x + (y/8)*LCDWIDTH] &= ~_BV((y%8)); | |||
} | |||
} | |||
/** \brief Draw line with color and mode. | |||
Draw line using color and mode from x0,y0 to x1,y1 of the screen buffer. | |||
*/ | |||
void draw_line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t color, uint8_t mode) { | |||
uint8_t steep = abs(y1 - y0) > abs(x1 - x0); | |||
if (steep) { | |||
swap(x0, y0); | |||
swap(x1, y1); | |||
} | |||
if (x0 > x1) { | |||
swap(x0, x1); | |||
swap(y0, y1); | |||
} | |||
uint8_t dx, dy; | |||
dx = x1 - x0; | |||
dy = abs(y1 - y0); | |||
int8_t err = dx / 2; | |||
int8_t ystep; | |||
if (y0 < y1) { | |||
ystep = 1; | |||
} else { | |||
ystep = -1;} | |||
for (; x0<x1; x0++) { | |||
if (steep) { | |||
draw_pixel(y0, x0, color, mode); | |||
} else { | |||
draw_pixel(x0, y0, color, mode); | |||
} | |||
err -= dy; | |||
if (err < 0) { | |||
y0 += ystep; | |||
err += dx; | |||
} | |||
} | |||
} | |||
/** \brief Draw horizontal line with color and mode. | |||
Draw horizontal line using color and mode from x,y to x+width,y of the screen buffer. | |||
*/ | |||
void draw_line_hori(uint8_t x, uint8_t y, uint8_t width, uint8_t color, uint8_t mode) { | |||
draw_line(x,y,x+width,y,color,mode); | |||
} | |||
/** \brief Draw vertical line. | |||
Draw vertical line using current fore color and current draw mode from x,y to x,y+height of the screen buffer. | |||
*/ | |||
void draw_line_vert(uint8_t x, uint8_t y, uint8_t height, bool color, uint8_t mode) { | |||
draw_line(x,y,x,y+height,color,mode); | |||
} | |||
/** \brief Draw rectangle with color and mode. | |||
Draw rectangle using color and mode from x,y to x+width,y+height of the screen buffer. | |||
*/ | |||
void draw_rect(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode) { | |||
uint8_t tempHeight; | |||
draw_line_hori(x,y, width, color, mode); | |||
draw_line_hori(x,y+height-1, width, color, mode); | |||
tempHeight=height-2; | |||
// skip drawing vertical lines to avoid overlapping of pixel that will | |||
// affect XOR plot if no pixel in between horizontal lines | |||
if (tempHeight<1) return; | |||
draw_line_vert(x,y+1, tempHeight, color, mode); | |||
draw_line_vert(x+width-1, y+1, tempHeight, color, mode); | |||
} | |||
/** \brief Draw rectangle with color and mode. | |||
Draw rectangle using color and mode from x,y to x+width,y+height of the screen buffer. | |||
*/ | |||
void draw_rect_soft(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode) { | |||
uint8_t tempHeight; | |||
draw_line_hori(x+1,y, width-2, color, mode); | |||
draw_line_hori(x+1,y+height-1, width-2, color, mode); | |||
tempHeight=height-2; | |||
// skip drawing vertical lines to avoid overlapping of pixel that will | |||
// affect XOR plot if no pixel in between horizontal lines | |||
if (tempHeight<1) return; | |||
draw_line_vert(x,y+1, tempHeight, color, mode); | |||
draw_line_vert(x+width-1, y+1, tempHeight, color, mode); | |||
} | |||
/** \brief Draw filled rectangle with color and mode. | |||
Draw filled rectangle using color and mode from x,y to x+width,y+height of the screen buffer. | |||
*/ | |||
void draw_rect_filled(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode) { | |||
// TODO - need to optimise the memory map draw so that this function will not call pixel one by one | |||
for (int i=x; i<x+width;i++) { | |||
draw_line_vert(i,y, height, color, mode); | |||
} | |||
} | |||
/** \brief Draw filled rectangle with color and mode. | |||
Draw filled rectangle using color and mode from x,y to x+width,y+height of the screen buffer. | |||
*/ | |||
void draw_rect_filled_soft(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode) { | |||
// TODO - need to optimise the memory map draw so that this function will not call pixel one by one | |||
for (int i=x; i<x+width;i++) { | |||
if (i == x || i == (x + width - 1)) | |||
draw_line_vert(i, y+1, height-2, color, mode); | |||
else | |||
draw_line_vert(i, y, height, color, mode); | |||
} | |||
} | |||
/** \brief Draw character with color and mode. | |||
Draw character c using color and draw mode at x,y. | |||
*/ | |||
void draw_char(uint8_t x, uint8_t y, uint8_t c, uint8_t color, uint8_t mode, uint8_t font) { | |||
// TODO - New routine to take font of any height, at the moment limited to font height in multiple of 8 pixels | |||
uint8_t rowsToDraw,row, tempC; | |||
uint8_t i,j,temp; | |||
uint16_t charPerBitmapRow,charColPositionOnBitmap,charRowPositionOnBitmap,charBitmapStartPosition; | |||
if ((font>=TOTALFONTS) || (font<0)) | |||
return; | |||
uint8_t fontType = font; | |||
uint8_t fontWidth = pgm_read_byte(fonts_pointer[fontType]+0); | |||
uint8_t fontHeight = pgm_read_byte(fonts_pointer[fontType]+1); | |||
uint8_t fontStartChar = pgm_read_byte(fonts_pointer[fontType]+2); | |||
uint8_t fontTotalChar = pgm_read_byte(fonts_pointer[fontType]+3); | |||
uint16_t fontMapWidth = (pgm_read_byte(fonts_pointer[fontType]+4)*100)+pgm_read_byte(fonts_pointer[fontType]+5); // two bytes values into integer 16 | |||
if ((c<fontStartChar) || (c>(fontStartChar+fontTotalChar-1))) // no bitmap for the required c | |||
return; | |||
tempC=c-fontStartChar; | |||
// each row (in datasheet is call page) is 8 bits high, 16 bit high character will have 2 rows to be drawn | |||
rowsToDraw=fontHeight/8; // 8 is LCD's page size, see SSD1306 datasheet | |||
if (rowsToDraw<=1) rowsToDraw=1; | |||
// the following draw function can draw anywhere on the screen, but SLOW pixel by pixel draw | |||
if (rowsToDraw==1) { | |||
for (i=0;i<fontWidth+1;i++) { | |||
if (i==fontWidth) // this is done in a weird way because for 5x7 font, there is no margin, this code add a margin after col 5 | |||
temp=0; | |||
else | |||
temp=pgm_read_byte(fonts_pointer[fontType]+FONTHEADERSIZE+(tempC*fontWidth)+i); | |||
for (j=0;j<8;j++) { // 8 is the LCD's page height (see datasheet for explanation) | |||
if (temp & 0x1) { | |||
draw_pixel(x+i, y+j, color,mode); | |||
} | |||
else { | |||
draw_pixel(x+i, y+j, !color,mode); | |||
} | |||
temp >>=1; | |||
} | |||
} | |||
return; | |||
} | |||
// font height over 8 bit | |||
// take character "0" ASCII 48 as example | |||
charPerBitmapRow = fontMapWidth/fontWidth; // 256/8 =32 char per row | |||
charColPositionOnBitmap = tempC % charPerBitmapRow; // =16 | |||
charRowPositionOnBitmap = (int)(tempC/charPerBitmapRow); // =1 | |||
charBitmapStartPosition = (charRowPositionOnBitmap * fontMapWidth * (fontHeight/8)) + (charColPositionOnBitmap * fontWidth) ; | |||
// each row on LCD is 8 bit height (see datasheet for explanation) | |||
for(row=0;row<rowsToDraw;row++) { | |||
for (i=0; i<fontWidth;i++) { | |||
temp=pgm_read_byte(fonts_pointer[fontType]+FONTHEADERSIZE+(charBitmapStartPosition+i+(row*fontMapWidth))); | |||
for (j=0;j<8;j++) { // 8 is the LCD's page height (see datasheet for explanation) | |||
if (temp & 0x1) { | |||
draw_pixel(x+i,y+j+(row*8), color, mode); | |||
} | |||
else { | |||
draw_pixel(x+i,y+j+(row*8), !color, mode); | |||
} | |||
temp >>=1; | |||
} | |||
} | |||
} | |||
} | |||
void draw_string(uint8_t x, uint8_t y, char * string, uint8_t color, uint8_t mode, uint8_t font) { | |||
if ((font>=TOTALFONTS) || (font<0)) | |||
return; | |||
uint8_t fontType = font; | |||
uint8_t fontWidth = pgm_read_byte(fonts_pointer[fontType]+0); | |||
uint8_t cur_x = x; | |||
for (int i = 0; i < strlen(string); i++) { | |||
draw_char(cur_x, y, string[i], color, mode, font); | |||
cur_x += fontWidth + 1; | |||
} | |||
} |
@ -0,0 +1,134 @@ | |||
/* Jim Lindblom @ SparkFun Electronics | |||
* October 26, 2014 | |||
* https://github.com/sparkfun/Micro_OLED_Breakout/tree/master/Firmware/Arduino/libraries/SFE_MicroOLED | |||
* | |||
* Modified by: | |||
* Emil Varughese @ Edwin Robotics Pvt. Ltd. | |||
* July 27, 2015 | |||
* https://github.com/emil01/SparkFun_Micro_OLED_Arduino_Library/ | |||
* | |||
* This code was heavily based around the MicroView library, written by GeekAmmo | |||
* (https://github.com/geekammo/MicroView-Arduino-Library). | |||
* | |||
* Adapted for QMK by: | |||
* Jack Humbert <jack.humb@gmail.com> | |||
* October 11, 2018 | |||
* | |||
* This program is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#pragma once | |||
#include "qwiic.h" | |||
void micro_oled_init(void); | |||
void send_command(uint8_t command); | |||
void send_data(uint8_t data); | |||
void set_page_address(uint8_t address); | |||
void set_column_address(uint8_t address); | |||
void clear_screen(void); | |||
void clear_buffer(void); | |||
void send_buffer(void); | |||
void draw_pixel(uint8_t x, uint8_t y, uint8_t color, uint8_t mode); | |||
void draw_line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t color, uint8_t mode); | |||
void draw_line_hori(uint8_t x, uint8_t y, uint8_t width, uint8_t color, uint8_t mode); | |||
void draw_line_vert(uint8_t x, uint8_t y, uint8_t height, bool color, uint8_t mode); | |||
void draw_rect(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode); | |||
void draw_rect_soft(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode); | |||
void draw_rect_filled(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode); | |||
void draw_rect_filled_soft(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t color, uint8_t mode); | |||
void draw_char(uint8_t x, uint8_t y, uint8_t c, uint8_t color, uint8_t mode, uint8_t font); | |||
void draw_string(uint8_t x, uint8_t y, char * string, uint8_t color, uint8_t mode, uint8_t font); | |||
#define I2C_ADDRESS_SA0_0 0b0111100 | |||
#ifndef I2C_ADDRESS_SA0_1 | |||
#define I2C_ADDRESS_SA0_1 0b0111101 | |||
#endif | |||
#define I2C_COMMAND 0x00 | |||
#define I2C_DATA 0x40 | |||
#define PIXEL_OFF 0 | |||
#define PIXEL_ON 1 | |||
#ifndef LCDWIDTH | |||
#define LCDWIDTH 64 | |||
#endif | |||
#ifndef LCDWIDTH | |||
#define LCDHEIGHT 48 | |||
#endif | |||
#define FONTHEADERSIZE 6 | |||
#define NORM 0 | |||
#define XOR 1 | |||
#define PAGE 0 | |||
#define ALL 1 | |||
#define WIDGETSTYLE0 0 | |||
#define WIDGETSTYLE1 1 | |||
#define WIDGETSTYLE2 2 | |||
#define SETCONTRAST 0x81 | |||
#define DISPLAYALLONRESUME 0xA4 | |||
#define DISPLAYALLON 0xA5 | |||
#define NORMALDISPLAY 0xA6 | |||
#define INVERTDISPLAY 0xA7 | |||
#define DISPLAYOFF 0xAE | |||
#define DISPLAYON 0xAF | |||
#define SETDISPLAYOFFSET 0xD3 | |||
#define SETCOMPINS 0xDA | |||
#define SETVCOMDESELECT 0xDB | |||
#define SETDISPLAYCLOCKDIV 0xD5 | |||
#define SETPRECHARGE 0xD9 | |||
#define SETMULTIPLEX 0xA8 | |||
#define SETLOWCOLUMN 0x00 | |||
#define SETHIGHCOLUMN 0x10 | |||
#define SETSTARTLINE 0x40 | |||
#define MEMORYMODE 0x20 | |||
#define COMSCANINC 0xC0 | |||
#define COMSCANDEC 0xC8 | |||
#define SEGREMAP 0xA0 | |||
#define CHARGEPUMP 0x8D | |||
#define EXTERNALVCC 0x01 | |||
#define SWITCHCAPVCC 0x02 | |||
// Scroll | |||
#define ACTIVATESCROLL 0x2F | |||
#define DEACTIVATESCROLL 0x2E | |||
#define SETVERTICALSCROLLAREA 0xA3 | |||
#define RIGHTHORIZONTALSCROLL 0x26 | |||
#define LEFT_HORIZONTALSCROLL 0x27 | |||
#define VERTICALRIGHTHORIZONTALSCROLL 0x29 | |||
#define VERTICALLEFTHORIZONTALSCROLL 0x2A | |||
typedef enum CMD { | |||
CMD_CLEAR, //0 | |||
CMD_INVERT, //1 | |||
CMD_CONTRAST, //2 | |||
CMD_DISPLAY, //3 | |||
CMD_SETCURSOR, //4 | |||
CMD_PIXEL, //5 | |||
CMD_LINE, //6 | |||
CMD_LINEH, //7 | |||
CMD_LINEV, //8 | |||
CMD_RECT, //9 | |||
CMD_RECTFILL, //10 | |||
CMD_CIRCLE, //11 | |||
CMD_CIRCLEFILL, //12 | |||
CMD_DRAWCHAR, //13 | |||
CMD_DRAWBITMAP, //14 | |||
CMD_GETLCDWIDTH, //15 | |||
CMD_GETLCDHEIGHT, //16 | |||
CMD_SETCOLOR, //17 | |||
CMD_SETDRAWMODE //18 | |||
} commCommand_t; |
@ -0,0 +1,31 @@ | |||
/* Copyright 2018 Jack Humbert <jack.humb@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 "qwiic.h" | |||
void qwiic_init(void) { | |||
#ifdef QWIIC_JOYSTIIC_ENABLE | |||
joystiic_init(); | |||
#endif | |||
#ifdef QWIIC_MICRO_OLED_ENABLE | |||
micro_oled_init(); | |||
#endif | |||
} | |||
void qwiic_task(void) { | |||
#ifdef QWIIC_JOYSTIIC_ENABLE | |||
joystiic_task(); | |||
#endif | |||
} |
@ -0,0 +1,28 @@ | |||
/* Copyright 2018 Jack Humbert <jack.humb@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 | |||
#include "i2c_master.h" | |||
#ifdef QWIIC_JOYSTIIC_ENABLE | |||
#include "joystiic.h" | |||
#endif | |||
#ifdef QWIIC_MICRO_OLED_ENABLE | |||
#include "micro_oled.h" | |||
#endif | |||
void qwiic_init(void); | |||
void qwiic_task(void); |
@ -0,0 +1,18 @@ | |||
ifneq ($(strip $(QWIIC_ENABLE)),) | |||
COMMON_VPATH += $(DRIVER_PATH)/qwiic | |||
OPT_DEFS += -DQWIIC_ENABLE | |||
SRC += qwiic.c | |||
ifeq ($(filter "i2c_master.c", $(SRC)),) | |||
SRC += i2c_master.c | |||
endif | |||
endif | |||
ifneq ($(filter JOYSTIIC, $(QWIIC_ENABLE)),) | |||
OPT_DEFS += -DQWIIC_JOYSTIIC_ENABLE | |||
SRC += joystiic.c | |||
endif | |||
ifneq ($(filter MICRO_OLED, $(QWIIC_ENABLE)),) | |||
OPT_DEFS += -DQWIIC_MICRO_OLED_ENABLE | |||
SRC += micro_oled.c | |||
endif |
@ -0,0 +1,288 @@ | |||
/****************************************************************************** | |||
font5x7.h | |||
Definition for small font | |||
This file was imported from the MicroView library, written by GeekAmmo | |||
(https://github.com/geekammo/MicroView-Arduino-Library), and released under | |||
the terms of the GNU General Public License as published by the Free Software | |||
Foundation, either version 3 of the License, or (at your option) any later | |||
version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
Modified by: | |||
Emil Varughese @ Edwin Robotics Pvt. Ltd. | |||
July 27, 2015 | |||
https://github.com/emil01/SparkFun_Micro_OLED_Arduino_Library/ | |||
******************************************************************************/ | |||
#pragma once | |||
#include "progmem.h" | |||
// Standard ASCII 5x7 font | |||
static const unsigned char font5x7[] PROGMEM = { | |||
// first row defines - FONTWIDTH, FONTHEIGHT, ASCII START CHAR, TOTAL CHARACTERS, FONT MAP WIDTH HIGH, FONT MAP WIDTH LOW (2,56 meaning 256) | |||
5,8,0,255,12,75, | |||
0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x3E, 0x5B, 0x4F, 0x5B, 0x3E, | |||
0x3E, 0x6B, 0x4F, 0x6B, 0x3E, | |||
0x1C, 0x3E, 0x7C, 0x3E, 0x1C, | |||
0x18, 0x3C, 0x7E, 0x3C, 0x18, | |||
0x1C, 0x57, 0x7D, 0x57, 0x1C, | |||
0x1C, 0x5E, 0x7F, 0x5E, 0x1C, | |||
0x00, 0x18, 0x3C, 0x18, 0x00, | |||
0xFF, 0xE7, 0xC3, 0xE7, 0xFF, | |||
0x00, 0x18, 0x24, 0x18, 0x00, | |||
0xFF, 0xE7, 0xDB, 0xE7, 0xFF, | |||
0x30, 0x48, 0x3A, 0x06, 0x0E, | |||
0x26, 0x29, 0x79, 0x29, 0x26, | |||
0x40, 0x7F, 0x05, 0x05, 0x07, | |||
0x40, 0x7F, 0x05, 0x25, 0x3F, | |||
0x5A, 0x3C, 0xE7, 0x3C, 0x5A, | |||
0x7F, 0x3E, 0x1C, 0x1C, 0x08, | |||
0x08, 0x1C, 0x1C, 0x3E, 0x7F, | |||
0x14, 0x22, 0x7F, 0x22, 0x14, | |||
0x5F, 0x5F, 0x00, 0x5F, 0x5F, | |||
0x06, 0x09, 0x7F, 0x01, 0x7F, | |||
0x00, 0x66, 0x89, 0x95, 0x6A, | |||
0x60, 0x60, 0x60, 0x60, 0x60, | |||
0x94, 0xA2, 0xFF, 0xA2, 0x94, | |||
0x08, 0x04, 0x7E, 0x04, 0x08, | |||
0x10, 0x20, 0x7E, 0x20, 0x10, | |||
0x08, 0x08, 0x2A, 0x1C, 0x08, | |||
0x08, 0x1C, 0x2A, 0x08, 0x08, | |||
0x1E, 0x10, 0x10, 0x10, 0x10, | |||
0x0C, 0x1E, 0x0C, 0x1E, 0x0C, | |||
0x30, 0x38, 0x3E, 0x38, 0x30, | |||
0x06, 0x0E, 0x3E, 0x0E, 0x06, | |||
0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x5F, 0x00, 0x00, | |||
0x00, 0x07, 0x00, 0x07, 0x00, | |||
0x14, 0x7F, 0x14, 0x7F, 0x14, | |||
0x24, 0x2A, 0x7F, 0x2A, 0x12, | |||
0x23, 0x13, 0x08, 0x64, 0x62, | |||
0x36, 0x49, 0x56, 0x20, 0x50, | |||
0x00, 0x08, 0x07, 0x03, 0x00, | |||
0x00, 0x1C, 0x22, 0x41, 0x00, | |||
0x00, 0x41, 0x22, 0x1C, 0x00, | |||
0x2A, 0x1C, 0x7F, 0x1C, 0x2A, | |||
0x08, 0x08, 0x3E, 0x08, 0x08, | |||
0x00, 0x80, 0x70, 0x30, 0x00, | |||
0x08, 0x08, 0x08, 0x08, 0x08, | |||
0x00, 0x00, 0x60, 0x60, 0x00, | |||
0x20, 0x10, 0x08, 0x04, 0x02, | |||
0x3E, 0x51, 0x49, 0x45, 0x3E, | |||
0x00, 0x42, 0x7F, 0x40, 0x00, | |||
0x72, 0x49, 0x49, 0x49, 0x46, | |||
0x21, 0x41, 0x49, 0x4D, 0x33, | |||
0x18, 0x14, 0x12, 0x7F, 0x10, | |||
0x27, 0x45, 0x45, 0x45, 0x39, | |||
0x3C, 0x4A, 0x49, 0x49, 0x31, | |||
0x41, 0x21, 0x11, 0x09, 0x07, | |||
0x36, 0x49, 0x49, 0x49, 0x36, | |||
0x46, 0x49, 0x49, 0x29, 0x1E, | |||
0x00, 0x00, 0x14, 0x00, 0x00, | |||
0x00, 0x40, 0x34, 0x00, 0x00, | |||
0x00, 0x08, 0x14, 0x22, 0x41, | |||
0x14, 0x14, 0x14, 0x14, 0x14, | |||
0x00, 0x41, 0x22, 0x14, 0x08, | |||
0x02, 0x01, 0x59, 0x09, 0x06, | |||
0x3E, 0x41, 0x5D, 0x59, 0x4E, | |||
0x7C, 0x12, 0x11, 0x12, 0x7C, | |||
0x7F, 0x49, 0x49, 0x49, 0x36, | |||
0x3E, 0x41, 0x41, 0x41, 0x22, | |||
0x7F, 0x41, 0x41, 0x41, 0x3E, | |||
0x7F, 0x49, 0x49, 0x49, 0x41, | |||
0x7F, 0x09, 0x09, 0x09, 0x01, | |||
0x3E, 0x41, 0x41, 0x51, 0x73, | |||
0x7F, 0x08, 0x08, 0x08, 0x7F, | |||
0x00, 0x41, 0x7F, 0x41, 0x00, | |||
0x20, 0x40, 0x41, 0x3F, 0x01, | |||
0x7F, 0x08, 0x14, 0x22, 0x41, | |||
0x7F, 0x40, 0x40, 0x40, 0x40, | |||
0x7F, 0x02, 0x1C, 0x02, 0x7F, | |||
0x7F, 0x04, 0x08, 0x10, 0x7F, | |||
0x3E, 0x41, 0x41, 0x41, 0x3E, | |||
0x7F, 0x09, 0x09, 0x09, 0x06, | |||
0x3E, 0x41, 0x51, 0x21, 0x5E, | |||
0x7F, 0x09, 0x19, 0x29, 0x46, | |||
0x26, 0x49, 0x49, 0x49, 0x32, | |||
0x03, 0x01, 0x7F, 0x01, 0x03, | |||
0x3F, 0x40, 0x40, 0x40, 0x3F, | |||
0x1F, 0x20, 0x40, 0x20, 0x1F, | |||
0x3F, 0x40, 0x38, 0x40, 0x3F, | |||
0x63, 0x14, 0x08, 0x14, 0x63, | |||
0x03, 0x04, 0x78, 0x04, 0x03, | |||
0x61, 0x59, 0x49, 0x4D, 0x43, | |||
0x00, 0x7F, 0x41, 0x41, 0x41, | |||
0x02, 0x04, 0x08, 0x10, 0x20, | |||
0x00, 0x41, 0x41, 0x41, 0x7F, | |||
0x04, 0x02, 0x01, 0x02, 0x04, | |||
0x40, 0x40, 0x40, 0x40, 0x40, | |||
0x00, 0x03, 0x07, 0x08, 0x00, | |||
0x20, 0x54, 0x54, 0x78, 0x40, | |||
0x7F, 0x28, 0x44, 0x44, 0x38, | |||
0x38, 0x44, 0x44, 0x44, 0x28, | |||
0x38, 0x44, 0x44, 0x28, 0x7F, | |||
0x38, 0x54, 0x54, 0x54, 0x18, | |||
0x00, 0x08, 0x7E, 0x09, 0x02, | |||
0x18, 0xA4, 0xA4, 0x9C, 0x78, | |||
0x7F, 0x08, 0x04, 0x04, 0x78, | |||
0x00, 0x44, 0x7D, 0x40, 0x00, | |||
0x20, 0x40, 0x40, 0x3D, 0x00, | |||
0x7F, 0x10, 0x28, 0x44, 0x00, | |||
0x00, 0x41, 0x7F, 0x40, 0x00, | |||
0x7C, 0x04, 0x78, 0x04, 0x78, | |||
0x7C, 0x08, 0x04, 0x04, 0x78, | |||
0x38, 0x44, 0x44, 0x44, 0x38, | |||
0xFC, 0x18, 0x24, 0x24, 0x18, | |||
0x18, 0x24, 0x24, 0x18, 0xFC, | |||
0x7C, 0x08, 0x04, 0x04, 0x08, | |||
0x48, 0x54, 0x54, 0x54, 0x24, | |||
0x04, 0x04, 0x3F, 0x44, 0x24, | |||
0x3C, 0x40, 0x40, 0x20, 0x7C, | |||
0x1C, 0x20, 0x40, 0x20, 0x1C, | |||
0x3C, 0x40, 0x30, 0x40, 0x3C, | |||
0x44, 0x28, 0x10, 0x28, 0x44, | |||
0x4C, 0x90, 0x90, 0x90, 0x7C, | |||
0x44, 0x64, 0x54, 0x4C, 0x44, | |||
0x00, 0x08, 0x36, 0x41, 0x00, | |||
0x00, 0x00, 0x77, 0x00, 0x00, | |||
0x00, 0x41, 0x36, 0x08, 0x00, | |||
0x02, 0x01, 0x02, 0x04, 0x02, | |||
0x3C, 0x26, 0x23, 0x26, 0x3C, | |||
0x1E, 0xA1, 0xA1, 0x61, 0x12, | |||
0x3A, 0x40, 0x40, 0x20, 0x7A, | |||
0x38, 0x54, 0x54, 0x55, 0x59, | |||
0x21, 0x55, 0x55, 0x79, 0x41, | |||
0x21, 0x54, 0x54, 0x78, 0x41, | |||
0x21, 0x55, 0x54, 0x78, 0x40, | |||
0x20, 0x54, 0x55, 0x79, 0x40, | |||
0x0C, 0x1E, 0x52, 0x72, 0x12, | |||
0x39, 0x55, 0x55, 0x55, 0x59, | |||
0x39, 0x54, 0x54, 0x54, 0x59, | |||
0x39, 0x55, 0x54, 0x54, 0x58, | |||
0x00, 0x00, 0x45, 0x7C, 0x41, | |||
0x00, 0x02, 0x45, 0x7D, 0x42, | |||
0x00, 0x01, 0x45, 0x7C, 0x40, | |||
0xF0, 0x29, 0x24, 0x29, 0xF0, | |||
0xF0, 0x28, 0x25, 0x28, 0xF0, | |||
0x7C, 0x54, 0x55, 0x45, 0x00, | |||
0x20, 0x54, 0x54, 0x7C, 0x54, | |||
0x7C, 0x0A, 0x09, 0x7F, 0x49, | |||
0x32, 0x49, 0x49, 0x49, 0x32, | |||
0x32, 0x48, 0x48, 0x48, 0x32, | |||
0x32, 0x4A, 0x48, 0x48, 0x30, | |||
0x3A, 0x41, 0x41, 0x21, 0x7A, | |||
0x3A, 0x42, 0x40, 0x20, 0x78, | |||
0x00, 0x9D, 0xA0, 0xA0, 0x7D, | |||
0x39, 0x44, 0x44, 0x44, 0x39, | |||
0x3D, 0x40, 0x40, 0x40, 0x3D, | |||
0x3C, 0x24, 0xFF, 0x24, 0x24, | |||
0x48, 0x7E, 0x49, 0x43, 0x66, | |||
0x2B, 0x2F, 0xFC, 0x2F, 0x2B, | |||
0xFF, 0x09, 0x29, 0xF6, 0x20, | |||
0xC0, 0x88, 0x7E, 0x09, 0x03, | |||
0x20, 0x54, 0x54, 0x79, 0x41, | |||
0x00, 0x00, 0x44, 0x7D, 0x41, | |||
0x30, 0x48, 0x48, 0x4A, 0x32, | |||
0x38, 0x40, 0x40, 0x22, 0x7A, | |||
0x00, 0x7A, 0x0A, 0x0A, 0x72, | |||
0x7D, 0x0D, 0x19, 0x31, 0x7D, | |||
0x26, 0x29, 0x29, 0x2F, 0x28, | |||
0x26, 0x29, 0x29, 0x29, 0x26, | |||
0x30, 0x48, 0x4D, 0x40, 0x20, | |||
0x38, 0x08, 0x08, 0x08, 0x08, | |||
0x08, 0x08, 0x08, 0x08, 0x38, | |||
0x2F, 0x10, 0xC8, 0xAC, 0xBA, | |||
0x2F, 0x10, 0x28, 0x34, 0xFA, | |||
0x00, 0x00, 0x7B, 0x00, 0x00, | |||
0x08, 0x14, 0x2A, 0x14, 0x22, | |||
0x22, 0x14, 0x2A, 0x14, 0x08, | |||
0xAA, 0x00, 0x55, 0x00, 0xAA, | |||
0xAA, 0x55, 0xAA, 0x55, 0xAA, | |||
0x00, 0x00, 0x00, 0xFF, 0x00, | |||
0x10, 0x10, 0x10, 0xFF, 0x00, | |||
0x14, 0x14, 0x14, 0xFF, 0x00, | |||
0x10, 0x10, 0xFF, 0x00, 0xFF, | |||
0x10, 0x10, 0xF0, 0x10, 0xF0, | |||
0x14, 0x14, 0x14, 0xFC, 0x00, | |||
0x14, 0x14, 0xF7, 0x00, 0xFF, | |||
0x00, 0x00, 0xFF, 0x00, 0xFF, | |||
0x14, 0x14, 0xF4, 0x04, 0xFC, | |||
0x14, 0x14, 0x17, 0x10, 0x1F, | |||
0x10, 0x10, 0x1F, 0x10, 0x1F, | |||
0x14, 0x14, 0x14, 0x1F, 0x00, | |||
0x10, 0x10, 0x10, 0xF0, 0x00, | |||
0x00, 0x00, 0x00, 0x1F, 0x10, | |||
0x10, 0x10, 0x10, 0x1F, 0x10, | |||
0x10, 0x10, 0x10, 0xF0, 0x10, | |||
0x00, 0x00, 0x00, 0xFF, 0x10, | |||
0x10, 0x10, 0x10, 0x10, 0x10, | |||
0x10, 0x10, 0x10, 0xFF, 0x10, | |||
0x00, 0x00, 0x00, 0xFF, 0x14, | |||
0x00, 0x00, 0xFF, 0x00, 0xFF, | |||
0x00, 0x00, 0x1F, 0x10, 0x17, | |||
0x00, 0x00, 0xFC, 0x04, 0xF4, | |||
0x14, 0x14, 0x17, 0x10, 0x17, | |||
0x14, 0x14, 0xF4, 0x04, 0xF4, | |||
0x00, 0x00, 0xFF, 0x00, 0xF7, | |||
0x14, 0x14, 0x14, 0x14, 0x14, | |||
0x14, 0x14, 0xF7, 0x00, 0xF7, | |||
0x14, 0x14, 0x14, 0x17, 0x14, | |||
0x10, 0x10, 0x1F, 0x10, 0x1F, | |||
0x14, 0x14, 0x14, 0xF4, 0x14, | |||
0x10, 0x10, 0xF0, 0x10, 0xF0, | |||
0x00, 0x00, 0x1F, 0x10, 0x1F, | |||
0x00, 0x00, 0x00, 0x1F, 0x14, | |||
0x00, 0x00, 0x00, 0xFC, 0x14, | |||
0x00, 0x00, 0xF0, 0x10, 0xF0, | |||
0x10, 0x10, 0xFF, 0x10, 0xFF, | |||
0x14, 0x14, 0x14, 0xFF, 0x14, | |||
0x10, 0x10, 0x10, 0x1F, 0x00, | |||
0x00, 0x00, 0x00, 0xF0, 0x10, | |||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | |||
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, | |||
0xFF, 0xFF, 0xFF, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0xFF, 0xFF, | |||
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, | |||
0x38, 0x44, 0x44, 0x38, 0x44, | |||
0x7C, 0x2A, 0x2A, 0x3E, 0x14, | |||
0x7E, 0x02, 0x02, 0x06, 0x06, | |||
0x02, 0x7E, 0x02, 0x7E, 0x02, | |||
0x63, 0x55, 0x49, 0x41, 0x63, | |||
0x38, 0x44, 0x44, 0x3C, 0x04, | |||
0x40, 0x7E, 0x20, 0x1E, 0x20, | |||
0x06, 0x02, 0x7E, 0x02, 0x02, | |||
0x99, 0xA5, 0xE7, 0xA5, 0x99, | |||
0x1C, 0x2A, 0x49, 0x2A, 0x1C, | |||
0x4C, 0x72, 0x01, 0x72, 0x4C, | |||
0x30, 0x4A, 0x4D, 0x4D, 0x30, | |||
0x30, 0x48, 0x78, 0x48, 0x30, | |||
0xBC, 0x62, 0x5A, 0x46, 0x3D, | |||
0x3E, 0x49, 0x49, 0x49, 0x00, | |||
0x7E, 0x01, 0x01, 0x01, 0x7E, | |||
0x2A, 0x2A, 0x2A, 0x2A, 0x2A, | |||
0x44, 0x44, 0x5F, 0x44, 0x44, | |||
0x40, 0x51, 0x4A, 0x44, 0x40, | |||
0x40, 0x44, 0x4A, 0x51, 0x40, | |||
0x00, 0x00, 0xFF, 0x01, 0x03, | |||
0xE0, 0x80, 0xFF, 0x00, 0x00, | |||
0x08, 0x08, 0x6B, 0x6B, 0x08, | |||
0x36, 0x12, 0x36, 0x24, 0x36, | |||
0x06, 0x0F, 0x09, 0x0F, 0x06, | |||
0x00, 0x00, 0x18, 0x18, 0x00, | |||
0x00, 0x00, 0x10, 0x10, 0x00, | |||
0x30, 0x40, 0xFF, 0x01, 0x01, | |||
0x00, 0x1F, 0x01, 0x01, 0x1E, | |||
0x00, 0x19, 0x1D, 0x17, 0x12, | |||
0x00, 0x3C, 0x3C, 0x3C, 0x3C, | |||
0x00, 0x00, 0x00, 0x00, 0x00 | |||
}; |
@ -0,0 +1,127 @@ | |||
/****************************************************************************** | |||
font8x16.h | |||
Definition for medium font | |||
This file was imported from the MicroView library, written by GeekAmmo | |||
(https://github.com/geekammo/MicroView-Arduino-Library), and released under | |||
the terms of the GNU General Public License as published by the Free Software | |||
Foundation, either version 3 of the License, or (at your option) any later | |||
version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
Modified by: | |||
Emil Varughese @ Edwin Robotics Pvt. Ltd. | |||
July 27, 2015 | |||
https://github.com/emil01/SparkFun_Micro_OLED_Arduino_Library/ | |||
******************************************************************************/ | |||
#pragma once | |||
#include "progmem.h" | |||
static const unsigned char font8x16[] PROGMEM = { | |||
// first row defines - FONTWIDTH, FONTHEIGHT, ASCII START CHAR, TOTAL CHARACTERS, FONT MAP WIDTH HIGH, FONT MAP WIDTH LOW (2,56 meaning 256) | |||
8,16,32,96,2,56, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xBE, 0x90, 0xD0, 0xBE, 0x90, 0x00, | |||
0x00, 0x1C, 0x62, 0xFF, 0xC2, 0x80, 0x00, 0x00, 0x0C, 0x12, 0x92, 0x4C, 0xB0, 0x88, 0x06, 0x00, | |||
0x80, 0x7C, 0x62, 0xB2, 0x1C, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0xE0, 0x18, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x04, 0x18, 0xE0, 0x00, 0x00, | |||
0x00, 0x24, 0x18, 0x7E, 0x18, 0x24, 0x00, 0x00, 0x80, 0x80, 0x80, 0xF0, 0x80, 0x80, 0x80, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x18, 0x06, 0x00, 0x00, | |||
0xF8, 0x04, 0xC2, 0x32, 0x0C, 0xF8, 0x00, 0x00, 0x00, 0x04, 0x04, 0xFE, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x02, 0x82, 0x42, 0x22, 0x1C, 0x00, 0x00, 0x00, 0x02, 0x22, 0x22, 0x22, 0xDC, 0x00, 0x00, | |||
0xC0, 0xA0, 0x98, 0x84, 0xFE, 0x80, 0x80, 0x00, 0x00, 0x1E, 0x12, 0x12, 0x22, 0xC2, 0x00, 0x00, | |||
0xF8, 0x44, 0x22, 0x22, 0x22, 0xC0, 0x00, 0x00, 0x00, 0x02, 0x02, 0xC2, 0x32, 0x0A, 0x06, 0x00, | |||
0x00, 0x8C, 0x52, 0x22, 0x52, 0x8C, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x26, 0xF8, 0x00, 0x00, | |||
0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, | |||
0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, | |||
0x10, 0x20, 0x20, 0x40, 0x40, 0x80, 0x80, 0x00, 0x00, 0x02, 0x82, 0x42, 0x22, 0x1C, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, | |||
0x00, 0x04, 0x04, 0x0F, 0x04, 0x03, 0x00, 0x00, 0x04, 0x02, 0x01, 0x03, 0x04, 0x04, 0x03, 0x00, | |||
0x03, 0x04, 0x04, 0x04, 0x05, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x03, 0x06, 0x08, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x06, 0x03, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x16, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x01, 0x03, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x04, 0x04, 0x07, 0x04, 0x04, 0x00, 0x00, | |||
0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, | |||
0x01, 0x02, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x03, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, | |||
0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x0E, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x04, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, | |||
0x04, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0xF8, 0x04, 0x72, 0x8A, 0xFA, 0x84, 0x78, 0x00, 0x00, 0xC0, 0x38, 0x06, 0x38, 0xC0, 0x00, 0x00, | |||
0x00, 0xFE, 0x22, 0x22, 0x22, 0xDC, 0x00, 0x00, 0xF8, 0x04, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, | |||
0xFE, 0x02, 0x02, 0x02, 0x04, 0xF8, 0x00, 0x00, 0x00, 0xFE, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, | |||
0x00, 0xFE, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0xF8, 0x04, 0x02, 0x02, 0x22, 0xE2, 0x00, 0x00, | |||
0xFE, 0x20, 0x20, 0x20, 0x20, 0xFE, 0x00, 0x00, 0x00, 0x02, 0x02, 0xFE, 0x02, 0x02, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x02, 0x02, 0xFE, 0x00, 0x00, 0xFE, 0x40, 0xB0, 0x08, 0x04, 0x02, 0x00, 0x00, | |||
0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x0C, 0x70, 0x80, 0x70, 0x0C, 0xFE, 0x00, | |||
0xFE, 0x0C, 0x30, 0xC0, 0x00, 0xFE, 0x00, 0x00, 0xF8, 0x04, 0x02, 0x02, 0x04, 0xF8, 0x00, 0x00, | |||
0xFE, 0x42, 0x42, 0x42, 0x22, 0x1C, 0x00, 0x00, 0xF8, 0x04, 0x02, 0x02, 0x04, 0xF8, 0x00, 0x00, | |||
0x00, 0xFE, 0x42, 0x42, 0xA2, 0x1C, 0x00, 0x00, 0x00, 0x1C, 0x22, 0x42, 0x42, 0x80, 0x00, 0x00, | |||
0x02, 0x02, 0x02, 0xFE, 0x02, 0x02, 0x02, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, | |||
0x06, 0x38, 0xC0, 0x00, 0xC0, 0x38, 0x06, 0x00, 0x3E, 0xC0, 0xF0, 0x0E, 0xF0, 0xC0, 0x3E, 0x00, | |||
0x00, 0x06, 0x98, 0x60, 0x98, 0x06, 0x00, 0x00, 0x00, 0x06, 0x18, 0xE0, 0x18, 0x06, 0x00, 0x00, | |||
0x02, 0x02, 0xC2, 0x32, 0x0A, 0x06, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x02, 0x02, 0x02, 0x02, 0x00, | |||
0x00, 0x06, 0x18, 0x60, 0x80, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0xFE, 0x00, 0x00, 0x00, | |||
0x40, 0x30, 0x0C, 0x0C, 0x30, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x01, 0x02, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x06, 0x00, | |||
0x00, 0x07, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x01, 0x02, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, | |||
0x07, 0x04, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, | |||
0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x04, 0x04, 0x07, 0x00, 0x00, | |||
0x07, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x04, 0x07, 0x04, 0x04, 0x00, 0x00, | |||
0x00, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x01, 0x02, 0x04, 0x00, 0x00, | |||
0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x07, 0x00, | |||
0x07, 0x00, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, | |||
0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x0C, 0x12, 0x11, 0x10, 0x00, | |||
0x00, 0x07, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, | |||
0x00, 0x00, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, | |||
0x00, 0x06, 0x01, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, | |||
0x06, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x00, 0x10, 0x10, 0x10, 0x10, 0x1F, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, | |||
0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0xF0, 0x00, 0x00, | |||
0x00, 0xFE, 0x20, 0x10, 0x10, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, | |||
0x00, 0xE0, 0x10, 0x10, 0x10, 0xFE, 0x00, 0x00, 0x00, 0xE0, 0x90, 0x90, 0x90, 0xE0, 0x00, 0x00, | |||
0x00, 0x20, 0xFC, 0x22, 0x22, 0x22, 0x02, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0xF0, 0x00, 0x00, | |||
0x00, 0xFE, 0x20, 0x10, 0x10, 0xE0, 0x00, 0x00, 0x10, 0x10, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x10, 0x10, 0x10, 0xF2, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x80, 0x40, 0x20, 0x10, 0x00, 0x00, | |||
0x00, 0x02, 0x02, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x20, 0x10, 0xF0, 0x20, 0x10, 0xF0, 0x00, | |||
0x00, 0xF0, 0x20, 0x10, 0x10, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0xE0, 0x00, 0x00, | |||
0x00, 0xF0, 0x20, 0x10, 0x10, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0xF0, 0x00, 0x00, | |||
0x00, 0xF0, 0x20, 0x10, 0x10, 0x70, 0x00, 0x00, 0x00, 0x60, 0x90, 0x90, 0x90, 0x20, 0x00, 0x00, | |||
0x00, 0x20, 0x20, 0xFC, 0x20, 0x20, 0x20, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, | |||
0x00, 0x70, 0x80, 0x00, 0x80, 0x70, 0x00, 0x00, 0xF0, 0x00, 0xC0, 0x30, 0xC0, 0x00, 0xF0, 0x00, | |||
0x00, 0x30, 0xC0, 0xC0, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0xC0, 0x00, 0x80, 0x70, 0x00, 0x00, | |||
0x00, 0x10, 0x10, 0x90, 0x50, 0x30, 0x00, 0x00, 0x00, 0x80, 0x80, 0x7E, 0x02, 0x02, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x7E, 0x80, 0x80, 0x00, 0x00, | |||
0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x02, 0x07, 0x00, 0x00, | |||
0x00, 0x07, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, | |||
0x00, 0x03, 0x04, 0x04, 0x02, 0x07, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, | |||
0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x24, 0x24, 0x22, 0x1F, 0x00, 0x00, | |||
0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x07, 0x04, 0x04, 0x00, 0x00, 0x00, | |||
0x20, 0x20, 0x20, 0x20, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x02, 0x04, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x07, 0x04, 0x04, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, | |||
0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, | |||
0x00, 0x3F, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x02, 0x3F, 0x00, 0x00, | |||
0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x00, 0x00, 0x03, 0x04, 0x04, 0x02, 0x07, 0x00, 0x00, | |||
0x00, 0x00, 0x03, 0x04, 0x03, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x00, 0x01, 0x06, 0x01, 0x00, | |||
0x00, 0x06, 0x01, 0x01, 0x06, 0x00, 0x00, 0x00, 0x20, 0x20, 0x31, 0x0E, 0x03, 0x00, 0x00, 0x00, | |||
0x00, 0x06, 0x05, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x1F, 0x00, 0x00, 0x00, 0x00, | |||
0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | |||
}; |
@ -1,6 +1,4 @@ | |||
# 1up60hse default keymap | |||
# 1up60hse default keymap generated by QMK Configurator | |||
This is the default keymap provided by [1upkeyboards](https://www.1upkeyboards.com). | |||
This is the keymap used by [QMK Configurator](https://config.qmk.fm/#/1upkeyboards/1up60hse/LAYOUT_60_ansi) as default. | |||
## Notes | |||
- Software reset key is located on `Esc` on the third layer. |
@ -0,0 +1,15 @@ | |||
#pragma once | |||
/* tap dance stuff*/ | |||
#undef TAPPING_TERM | |||
#define TAPPING_TERM 500 | |||
#define TAPPING_TOGGLE 2 | |||
#define EXAMPLESTRING1 "tapdance_1" | |||
#define EXAMPLESTRING2 "tapdance_2" | |||
#define EXAMPLESTRING3 "tapdance_3" | |||
#define EXAMPLESTRING4 "tapdance_4" | |||
#undef RGBLED_NUM | |||
#define RGBLED_NUM 16 |
@ -0,0 +1,215 @@ | |||
/* | |||
tap danc eis turned on in the rules now... | |||
*/ | |||
#include QMK_KEYBOARD_H | |||
#define _EMOJI 0 | |||
#define _TAPLAND 1 | |||
#define _LEDCNTL 2 | |||
enum custom_keycodes { | |||
SHRUG, | |||
DISFACE, | |||
FU, | |||
TFLIP, | |||
TFLIP2, | |||
SAD_EYES, | |||
TPUT, | |||
HAPPYFACE, | |||
HEARTFACE, | |||
CLOUD, | |||
CHANFACE, | |||
CMDCLEAR | |||
}; | |||
//Tap Dance Declarations | |||
enum { | |||
TD_EXAMPLE1 = 0, | |||
TD_EXAMPLE2, | |||
TD_EXAMPLE3, | |||
TD_EXAMPLE4 | |||
}; | |||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||
/* EMOJI Pad | |||
* ,-------------------------------. | |||
* |TFLIP | TFlIP2|DISFACE| FU | | |||
* |------+-------+-------+--------| | |||
* | CLOUD| | | CLEAR | | |||
* |------+-------+-------+--------| | |||
* |SHRUG |DISFACE| HRTFAC| HAPPYF | | |||
* |------+-------+-------+--------| | |||
* | ENTER| |LEDCNTR| tapland| | |||
* `-------------------------------' | |||
*/ | |||
//purple | |||
[_EMOJI] = LAYOUT_ortho_4x4( | |||
TFLIP, TFLIP2, KC_NO, FU , | |||
CLOUD, KC_NO, KC_NO, CMDCLEAR, | |||
SHRUG, DISFACE, HEARTFACE, HAPPYFACE, | |||
KC_ENT, RGB_TOG, MO(_LEDCNTL), MO(_TAPLAND) | |||
), | |||
/* TapLand // | |||
* ,-------------------------------. | |||
* | str1 | str2 | str3 | str4 | | |||
* |------+-------+-------+--------| | |||
* | | | | | | |||
* |------+-------+-------+--------| | |||
* | | | | | | |||
* |------+-------+-------+--------| | |||
* | | | | | | |||
* `-------------------------------' | |||
*/ | |||
//blue | |||
[_TAPLAND] = LAYOUT_ortho_4x4( | |||
TD(TD_EXAMPLE1), TD(TD_EXAMPLE2), TD(TD_EXAMPLE3), TD(TD_EXAMPLE4), | |||
KC_NO, KC_NO, KC_NO, KC_NO, | |||
KC_NO, KC_NO, KC_NO, KC_NO, | |||
KC_NO, KC_NO, KC_NO, KC_NO | |||
), | |||
/* LEDControl Pad | |||
* ,-------------------------------. | |||
* | snake|breathe|rainbow|gradient| | |||
* |------+-------+-------+--------| | |||
* | xmas | Val+ | Sat+ | HUE+ | | |||
* |------+-------+-------+--------| | |||
* |kngrdr| Val- | Sat- | HUE- | | |||
* |------+-------+-------+--------| | |||
* | swirl| PLAIN | | ON/OFF | | |||
* `-------------------------------' | |||
*/ | |||
//blue | |||
[_LEDCNTL] = LAYOUT_ortho_4x4( | |||
RGB_M_SN, RGB_M_B, RGB_M_R, RGB_M_G, | |||
RGB_M_X, RGB_VAI, RGB_SAI, RGB_HUI, | |||
RGB_M_K, RGB_VAD, RGB_SAD, RGB_HUD, | |||
RGB_M_SW, RGB_M_P, KC_NO, RGB_TOG | |||
), | |||
}; | |||
bool process_record_user(uint16_t keycode, keyrecord_t *record) { | |||
if (record->event.pressed) { | |||
switch(keycode) { | |||
case CLOUD: // (っ◕‿◕)っ | |||
if(record->event.pressed){ | |||
send_unicode_hex_string("0028 3063 25D5 203F 25D5 0029 3063"); | |||
} | |||
return false; | |||
break; | |||
case FU: // t(-_-t) | |||
if(record->event.pressed){ | |||
SEND_STRING("t(-_-t)"); | |||
} | |||
return false; | |||
break; | |||
case HAPPYFACE: // ʘ‿ʘ | |||
if(record->event.pressed){ | |||
send_unicode_hex_string("0298 203F 0298"); | |||
} | |||
return false; | |||
break; | |||
case CMDCLEAR: | |||
if (record->event.pressed) { | |||
register_code(KC_LGUI); | |||
tap_code(KC_A); | |||
unregister_code(KC_LGUI); | |||
tap_code(KC_DEL); | |||
} | |||
return false; | |||
break; | |||
case SHRUG: // ¯\_(ツ)_/¯ | |||
if (record->event.pressed) { | |||
send_unicode_hex_string("00AF 005C 005F 0028 30C4 0029 005F 002F 00AF"); | |||
} | |||
return false; | |||
break; | |||
case HEARTFACE: // ♥‿♥ | |||
if(record->event.pressed){ | |||
send_unicode_hex_string("2665 203F 2665"); | |||
} | |||
return false; | |||
break; | |||
case DISFACE: // ಠ_ಠ | |||
if(record->event.pressed){ | |||
send_unicode_hex_string("0CA0 005F 0CA0"); | |||
} | |||
return false; | |||
break; | |||
case TFLIP: // (╯°□°)╯ ︵ ┻━┻ | |||
if(record->event.pressed){ | |||
send_unicode_hex_string("0028 256F 00B0 25A1 00B0 0029 256F 0020 FE35 0020 253B 2501 253B"); | |||
} | |||
return false; | |||
break; | |||
case TFLIP2: // ┻━┻︵ \(°□°)/ ︵ ┻━┻ | |||
if(record->event.pressed){ | |||
send_unicode_hex_string("253B 2501 253B FE35 0020 005C 0028 00B0 25A1 00B0 0029 002F 0020 FE35 0020 253B 2501 253B"); | |||
} | |||
return false; | |||
break; | |||
} | |||
} | |||
return true; | |||
} | |||
/* tap dance time */ | |||
void tdexample1(qk_tap_dance_state_t *state, void *user_data) { | |||
if (state->count >= 2) { | |||
SEND_STRING(EXAMPLESTRING1); | |||
reset_tap_dance (state); | |||
} | |||
} | |||
void tdexample2(qk_tap_dance_state_t *state, void *user_data) { | |||
if (state->count >= 2) { | |||
SEND_STRING(EXAMPLESTRING2); | |||
reset_tap_dance (state); | |||
} | |||
} | |||
void tdexample3(qk_tap_dance_state_t *state, void *user_data) { | |||
if (state->count >= 2) { | |||
SEND_STRING(EXAMPLESTRING3); | |||
reset_tap_dance (state); | |||
} | |||
} | |||
void tdexample4(qk_tap_dance_state_t *state, void *user_data) { | |||
if (state->count >= 2) { | |||
SEND_STRING(EXAMPLESTRING4); | |||
reset_tap_dance (state); | |||
} | |||
} | |||
qk_tap_dance_action_t tap_dance_actions[] = { | |||
[TD_EXAMPLE1] = ACTION_TAP_DANCE_FN(tdexample1), | |||
[TD_EXAMPLE2] = ACTION_TAP_DANCE_FN(tdexample2), | |||
[TD_EXAMPLE3] = ACTION_TAP_DANCE_FN(tdexample3), | |||
[TD_EXAMPLE4] = ACTION_TAP_DANCE_FN(tdexample4) | |||
}; | |||
// Runs just one time when the keyboard initializes. | |||
void matrix_scan_user(void) { | |||
static bool has_ran_yet; | |||
if (!has_ran_yet) { | |||
has_ran_yet = true; | |||
rgblight_setrgb (16, 0, 16); | |||
} | |||
} | |||
uint32_t layer_state_set_user(uint32_t state) { | |||
switch (biton32(state)) { | |||
case _TAPLAND: | |||
rgblight_setrgb(0, 16, 0); //green | |||
break; | |||
case _LEDCNTL: | |||
rgblight_setrgb(0, 0, 16); //blue | |||
break; | |||
case _EMOJI: | |||
rgblight_setrgb (16, 0, 16); //purple | |||
break; | |||
default: // for any other layers, or the default layer | |||
rgblight_setrgb (16, 0, 16); //purple | |||
break; | |||
} | |||
return state; | |||
} |
@ -0,0 +1,10 @@ | |||
# Ridingtraffic's examples | |||
=== | |||
This keymap has many features: | |||
3 layers | |||
Momentary layer switching | |||
16 pixel neopixel | |||
Unicode Enabled | |||
Tap dance enabled | |||
The rgb also updates depending on what layer you are on, and then flips back when done. |
@ -0,0 +1,5 @@ | |||
# turning on tap dance | |||
TAP_DANCE_ENABLE = yes | |||
RGBLIGHT_ENABLE = yes | |||
MOUSEKEY_ENABLE = no | |||
UNICODE_ENABLE = yes |
@ -0,0 +1 @@ | |||
#include "30wer.h" |
@ -0,0 +1,14 @@ | |||
#pragma once | |||
#include "quantum.h" | |||
#define LAYOUT( \ | |||
k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c, \ | |||
k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, k1c, \ | |||
k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b \ | |||
) \ | |||
{ \ | |||
{ k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c }, \ | |||
{ k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, k1c }, \ | |||
{ k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b } \ | |||
} |