Skip to content

Instantly share code, notes, and snippets.

@dentex
Created December 30, 2020 09:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dentex/98e6c38dd6b1af2cc13558d9303c3a0e to your computer and use it in GitHub Desktop.
Save dentex/98e6c38dd6b1af2cc13558d9303c3a0e to your computer and use it in GitHub Desktop.
Arduino sketch to Zoom in/out view and increase/decrease brush size in Krita, using a Digispark ATtiny85 board
/*
* Kritary - Krita Rotary Zoom and Brush Size Controller
* [Using a Digispark (ATtiny85) and a rotary encoder]
*
* Copyright (C) 2020 Samuele RINI <samuele.rini76 [AT] 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 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/>.
*
*
*
*
* ######################################################################################
* Realized adapting and modifing the two amazing pieces
* of code, [1] and [2], as noted below:
* ######################################################################################
*
*
*
*
* #####
* # 1 # --------------------------------------------------------------------------------
* #####
*
* ===== T H E K N O B =====
* Media Controller Mk III
* ----- By Frank Lumien -----
* www.lumien.se
* ===========================
* Arduino code by:
* IAmOrion aka James Tanner
* ===========================
*
* Version 2.0
* Changes in this fork
* FUNCTIONS --------------------
* Turn knob left: Volume down "-" to zoom out
* Turn knob right: Volume up "+" to zoom in
* Press knob: Play & Pause (alternating) zoom reset
* Press and turn knob left: Previous track decrease brush size
* Press and turn knob right: Next track increase brush size
*
* Note: You can change all of these functions, see Settings.h for more.
*
* PINOUT, Digispark to KY-040
* P0 to CLK
* P2 to DT
* P5 to SW // RESET disabled
* VIN to GND // reversed
* GND to +5V // reversed
* Note: The position of these pins may depend on your board and encoder.
* If you have already soldered or if The Knob doesn’t behave as expected,
* you can adjust the pin settings in Settings.h
*
* CONNECTING
* See https://digistump.com/wiki/digispark/tutorials/connecting for how
* to connect, get drivers and add set up Arduino for the Digispark bord.
*
* Set board to "Digispark (Default - 16.5Mhz)"
*
* COMPILING
* Get the Trinket library from https://github.com/adafruit/Adafruit-Trinket-USB/tree/master/TrinketHidCombo
* When compiling you will likely get warning messages related to the Trinket
* library. This is normal and does not mean that something is wrong. As long
* as the compilation finishes, you are good to go.
*
* #####
* # 2 # --------------------------------------------------------------------------------
* #####
*
* TinyMultimediaController - Multimedia controller using a Digispark
* (ATtiny85) and a rotary encoder
*
* Copyright (C) 2018 Costin STROIE <costinstroie@eridu.eu.org>
*
* 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 "DigiKeyboard.h"
//Pin settings
#define encoderPinA 2 // DT -- (volume DOWN)
#define encoderPinB 0 // CLK - (volume UP)
#define encoderButton 5
#define ROTARY_LED 1
// LED stuff
bool ledLight = false; // Status flag for the LED (on or off)
unsigned long ledTimeout = 0UL; // The time when the LED will turn off
unsigned long ledDelay = 30UL; // Time delay after which the LED turns off
// Function settings. To change any of the functions, replace
// the MMKEY_* commands with any of the examples below.
// all actions will be done with the
// LEFT CONTROL modifier, in the sketch
#define LEFT_ACTION 0x38 // "-"
#define LEFT_ACTION_MODE1 KEY_8
#define RIGHT_ACTION 0x30 // "+"
#define RIGHT_ACTION_MODE1 KEY_9
#define BUTTON_ACTION_SINGLE KEY_0
#define TRINKET
#include <avr/power.h>
#define LATCHSTATE 3
int buttonState = LOW, lastButtonState = LOW;
long lastDebounceTime = 0, debounceDelay = 50;
int _position = 0, _positionExt = 0;
int8_t _oldState; bool btnPressed=false, btnReleased=false, pressedRotary=false;
byte bitLed = _BV(ROTARY_LED);
const int8_t encoderStates[] = {
0, -1, 1, 0,
1, 0, 0, -1,
-1, 0, 0, 1,
0, 1, -1, 0
};
void setup() {
if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
pinMode(encoderPinA, INPUT);
pinMode(encoderPinB, INPUT);
pinMode(encoderButton, INPUT);
digitalWrite(encoderPinA, HIGH);
digitalWrite(encoderPinA, HIGH);
digitalWrite(encoderButton, LOW);
_oldState = 3;
// Set the LED pin to output and flash it longer
pinMode(ROTARY_LED, OUTPUT);
ledOn();
ledTimeout += ledDelay;
// this is generally not necessary but with some older systems it seems to
// prevent missing the first character after a delay:
DigiKeyboard.sendKeyStroke(0);
DigiKeyboard.delay(250);
}
/**
Send a media keypress
@param key the key code to send
*/
void keySend(byte key/* , byte mod */) {
// Turn the LED on
ledOn();
// Send the key
DigiKeyboard.sendKeyStroke(key, MOD_CONTROL_LEFT);
}
/*
Turn the LED on and set the timeout
*/
void ledOn() {
if (!ledLight) {
ledLight = true;
PORTB |= bitLed;
}
ledTimeout = millis() + ledDelay;
}
/*
Check the timeout and turn the LED off
@param nowMillis cached millis()
*/
void ledOff(unsigned long nowMillis) {
if (ledLight and (nowMillis > ledTimeout)) {
ledLight = false;
PORTB &= ~bitLed;
}
}
void loop() {
// Keep the time
unsigned long nowMillis = millis();
static int pos = 0;
tick();
int newPos = getPosition();
if (pos != newPos) {
if (newPos < pos) {
if (!btnPressed) {
keySend(LEFT_ACTION);
} else {
pressedRotary=true;
keySend(LEFT_ACTION_MODE1);
}
}
else if (newPos > pos){
if (!btnPressed) {
keySend(RIGHT_ACTION);
} else {
pressedRotary=true;
keySend(RIGHT_ACTION_MODE1);
}
}
pos = newPos;
}
int reading = digitalRead(encoderButton);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
if (buttonState == HIGH) {
btnPressed=true;
} else if (buttonState == LOW){
btnReleased=true;
}
}
}
lastButtonState = reading;
if (btnPressed == true && btnReleased ==true && pressedRotary ==false) {
keySend(BUTTON_ACTION_SINGLE);
btnPressed=false;btnReleased=false;
} else if (btnPressed == true && btnReleased == true && pressedRotary == true) {
//RELEASED_AFTER_HELD_ROTATION
btnPressed=false;btnReleased=false;pressedRotary=false;
}
// Turn the LED off, if timed out
ledOff(nowMillis);
}
int getPosition() {
return _positionExt;
}
void setPosition(int newPosition) {
_position = ((newPosition<<2) | (_position & 0x03));
_positionExt = newPosition;
}
void tick(void) {
int sig1 = digitalRead(encoderPinA);
int sig2 = digitalRead(encoderPinB);
int8_t thisState = sig1 | (sig2 << 1);
if (_oldState != thisState) {
_position += encoderStates[thisState | (_oldState<<2)];
if (thisState == LATCHSTATE)
_positionExt = _position >> 2;
_oldState = thisState;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment