I2C RotaryEncoderTx - Ino
I2C RotaryEncoderTx - Ino
===================================================================================
// Project: Rotary Encoder with I2C Interface based on ATtiny202/212/402/412
// Version: v1.0
// Year: 2022
// Author: Stefan Wagner
// Github: https://github.com/wagiminator
// EasyEDA: https://easyeda.com/wagiminator
// License: http://creativecommons.org/licenses/by-sa/3.0/
//
===================================================================================
//
// Description:
// ------------
// This is a simple implementation of the rotary encoder with I2C interface.
//
// Wiring:
// -------
// +-\/-+
// Vdd 1|° |8 GND
// ENC B --- TXD PA6 2| |7 PA3 AIN3 -------- ENC SW
// ENC A --- RXD PA7 3| |6 PA0 AIN0 UPDI --- UPDI
// I2C SDA --- SDA PA1 4| |5 PA2 AIN2 SCL ---- I2C SCL
// +----+
//
// Compilation Settings:
// ---------------------
// Core: megaTinyCore (https://github.com/SpenceKonde/megaTinyCore)
// Board: ATtiny412/402/212/202
// Chip: Choose the chip that is installed on the device
// Clock: 10 MHz internal
//
// Leave the rest on default settings. Don't forget to "Burn bootloader".
// Compile and upload the code.
//
// No Arduino core functions or libraries are used. To compile and upload without
// Arduino IDE download AVR 8-bit toolchain at:
// https://www.microchip.com/mplab/avr-support/avr-and-arm-toolchains-c-compilers
// and extract to tools/avr-gcc. Use the makefile to compile and upload.
//
// Fuse Settings: 0:0x00 1:0x00 2:0x02 4:0x00 5:0xC5 6:0x04 7:0x00 8:0x00
//
// Operating Instructions:
// -----------------------
// The device has four 16-bit and two 8-bit registers that can be read and written.
// The 16-bit registers are signed and the least significant byte is always
// transmitted first. With each access (reading or writing), the registers are
// always transferred starting with the first in the following order:
// 1. Encoder wheel value (16-bit)
// 2. Encoder switch state (8-bit, 0=switch released, 1=switch pressed)
// 3. Encoder wheel value loop flag (8-bit, 0=do not loop, 1=loop around)
// 4. Encoder wheel minimum value (16-bit)
// 5. Encoder wheel maximum value (16-bit)
// 6. Encoder wheel value change step (16-bit)
//
===================================================================================
// Libraries, Definitions and Macros
//
===================================================================================
// Libraries
#include <avr/io.h> // for GPIO
#include <avr/interrupt.h> // for interrupts
// Pin assignments
#define PIN_SDA PA1 // I2C Serial Data
#define PIN_SCL PA2 // I2C Serial Clock
#define PIN_ENC_SW PA3 // rotary encoder switch
#define PIN_ENC_B PA6 // rotary encoder B
#define PIN_ENC_A PA7 // rotary encoder A
// Firmware parameters
#define I2C_ADDR 0x36 // I2C address of the device
//
===================================================================================
// I2C Slave Implementation
//
===================================================================================
//
===================================================================================
// Rotary Encoder Implementation using Pin Change Interrupt
//
===================================================================================
// Global variables
volatile uint8_t ENC_a0, ENC_b0, ENC_ab0, ENC_loop, ENC_changed;
volatile int16_t ENC_count, ENC_countMin, ENC_countMax, ENC_countStep;
//
===================================================================================
// Main Function
//
===================================================================================
int main(void) {
// Local variables
int16_t rval, rmin, rmax, rstep; // for handling encoder
parameters
// Setup
_PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, 1); // set clock frequency to 10 MHz
I2C_init(); // setup I2C
ENC_init(); // setup rotary encoder
sei(); // enable interrupts
// Loop
while(1) {
// Update rotary encoder settings if I2C registers have changed
if(I2C_REG_changed && !I2C_busy) {
cli(); // disable interrupts for atomic
ops
rval = ((uint16_t)I2C_REG[1] << 8) |
(uint16_t)I2C_REG[0];
rmin = ((uint16_t)I2C_REG[5] << 8) |
(uint16_t)I2C_REG[4];
rmax = ((uint16_t)I2C_REG[7] << 8) |
(uint16_t)I2C_REG[6];
rstep = ((uint16_t)I2C_REG[9] << 8) |
(uint16_t)I2C_REG[8];
I2C_REG_changed = 0; // clear register changed flag
sei(); // enable interrupts again
ENC_set(rmin, rmax, rstep, rval, I2C_REG[3]); // set rotary encoder
}