If you're still looking, there's a hex file in theDanke schoen Rolf
Can you provide a compilled hex ? I haven't a platform io compiler
Firmware directory in their Github repo: rolfdegen/Jeannie-Open-source-Synthesizer// Abfrage für den Seven-Encoder auf Teensy und MCP23017
//
#include <Arduino.h>
#include <Wire.h>
#include <avr/interrupt.h>
#include <Adafruit_MCP23X17.h>
Adafruit_MCP23X17 mcp0; // Tasten 1-16
Adafruit_MCP23X17 mcp1; // Encoder
// Encoder-Variable
volatile uint16_t current_GPIO1 = 0;
uint16_t old_GPIO1 = 0;
int16_t Enc_Pos[7]= {0,0,0,0,0,0,0};
uint16_t currentClkState[7] = {0,0,0,0,0,0,0};
uint8_t Enc_B[7] = {0,0,0,0,0,0,0};
uint16_t lastClkState[7] = {0,0,0,0,0,0,0};
// Key interrupt ----------------------------------------------
void Key_Interrupt()
{
key_action = true;
}
// Encoder-Interrupt ----------------------------------------------
void Encoder_Interrupt()
{
enc_action = true;
current_GPIO1 = mcp1.readGPIOAB();
}
// read Encoder ------------------------------------------------
void read_enc(void)
{
if (enc_action)
{
uint8_t encID = 0;
enc_action = false;
// Check MCP23017 GPIO for activity
uint16_t changesBits = old_GPIO1 ^ current_GPIO1;
old_GPIO1 = current_GPIO1;
// Encoder1 Clk Pin status
if (changesBits == 256)
{
currentClkState[0] = bitRead(current_GPIO1, 8);
encID = 0;
} // Encode1 DT Pin status
else if (changesBits == 512)
{
Enc_B[0] = bitRead(current_GPIO1, 9);
encID = 0;
}
// Encoder1 Clk Pin status
else if (changesBits == 1024)
{
currentClkState[1] = bitRead(current_GPIO1, 10);
encID = 1;
} // Encode2 DT Pin status
else if (changesBits == 2048)
{
Enc_B[1] = bitRead(current_GPIO1, 11);
encID = 1;
}
// print encoder values
if (currentClkState[encID] != lastClkState[encID])
{
if (Enc_B[encID] != currentClkState[encID])
{
Enc_Pos[encID]++;
}
else
{
Enc_Pos[encID]--;
}
tft.setTextColor(ST7735_WHITE);
tft.setFont(OpenSans_16);
if (encID == 0)
{
tft.fillRect(90, 100, 60, 20, ST7735_RED);
tft.setCursor(100, 101);
}
else
{
tft.fillRect(90, 150, 60, 20, ST7735_BLUE);
tft.setCursor(100, 151);
}
tft.print(Enc_Pos[encID]);
tft.updateScreenAsyncT4();
}
lastClkState[encID] = currentClkState[encID];
old_GPIO1 = current_GPIO1;
}
}
// Setup -------------------------------------------------------
void setup(void)
{
Serial.begin(9600);
// Initializing the key/encoder MCP23017 I/O expander
mcp0.begin_I2C(0x21, &Wire1); // Adresse 0x20-0x27
mcp1.begin_I2C(0x22, &Wire1);
// Initialize Wire1 for encoder
Wire1.begin();
Wire1.setClock(400000UL); // I2C-Speed 400 kHz
// MPC23017(1-3) Expander for encoders & buttons
mcp0.setupInterrupts(true, false, LOW);
for (size_t i = 0; i < 16; i++)
{
mcp0.pinMode(i, INPUT_PULLUP);
mcp0.setupInterruptPin(i, CHANGE);
}
mcp0.getCapturedInterrupt();
mcp0.readGPIOAB();
mcp0.clearInterrupts();
mcp1.setupInterrupts(true, false, LOW);
for (size_t i = 0; i < 16; i++)
{
mcp1.pinMode(i, INPUT_PULLUP);
mcp1.setupInterruptPin(i, CHANGE);
}
mcp1.getCapturedInterrupt();
mcp1.readGPIOAB();
mcp1.clearInterrupts();
// init Key Interrupt
attachInterrupt(digitalPinToInterrupt(PIN_KEY_INT), Key_Interrupt, FALLING);
// init Encoder-Interrupt
attachInterrupt(digitalPinToInterrupt(PIN_ENC_INT), Encoder_Interrupt, FALLING);
}
void loop()
{
// Here are high-priority items
// lower priority here
if (loopCount++ > 15) // counter
{
//read_keys();
//read_ts();
read_enc();
loopCount = 0;
}
}
The Jeannie 2 is equipped with a total of seven high-quality encoders. These are used for parameter input in the menu and for modulation. Unfortunately, the Teensy 4.1 microcontroller in the Jeannie 2 doesn't have enough port pins to connect all the encoders. Therefore, I used an MCP23017 16-bit I/O expander for the encoder readings. This communicates with the Teensy 4.1 microcontroller via an I²C bus at a speed of 400 kHz.
// Abfrage für den Seven-Encoder auf Teensy und MCP23017
//
#include <Arduino.h>
#include <Wire.h>
#include <avr/interrupt.h>
#include <Adafruit_MCP23X17.h>
Adafruit_MCP23X17 mcp0; // Tasten 1-16
Adafruit_MCP23X17 mcp1; // Encoder
// Encoder-Variable
volatile uint16_t current_GPIO1 = 0;
uint16_t old_GPIO1 = 0;
int16_t Enc_Pos[7]= {0,0,0,0,0,0,0};
uint16_t currentClkState[7] = {0,0,0,0,0,0,0};
uint8_t Enc_B[7] = {0,0,0,0,0,0,0};
uint16_t lastClkState[7] = {0,0,0,0,0,0,0};
// JWP added these macros and variables
#define PIN_KEY_INT (1)
#define PIN_ENC_INT (2)
bool key_action;
bool enc_action;
int loopCount;
// Key interrupt ----------------------------------------------
void Key_Interrupt()
{
key_action = true;
}
// Encoder-Interrupt ----------------------------------------------
void Encoder_Interrupt()
{
enc_action = true;
current_GPIO1 = mcp1.readGPIOAB();
}
// read Encoder ------------------------------------------------
void read_enc(void)
{
if (enc_action)
{
uint8_t encID = 0;
enc_action = false;
// Check MCP23017 GPIO for activity
uint16_t changesBits = old_GPIO1 ^ current_GPIO1;
old_GPIO1 = current_GPIO1;
// Encoder1 Clk Pin status
if (changesBits == 256)
{
currentClkState[0] = bitRead(current_GPIO1, 8);
encID = 0;
} // Encode1 DT Pin status
else if (changesBits == 512)
{
Enc_B[0] = bitRead(current_GPIO1, 9);
encID = 0;
}
// Encoder1 Clk Pin status
else if (changesBits == 1024)
{
currentClkState[1] = bitRead(current_GPIO1, 10);
encID = 1;
} // Encode2 DT Pin status
else if (changesBits == 2048)
{
Enc_B[1] = bitRead(current_GPIO1, 11);
encID = 1;
}
// print encoder values
if (currentClkState[encID] != lastClkState[encID])
{
if (Enc_B[encID] != currentClkState[encID])
{
Enc_Pos[encID]++;
}
else
{
Enc_Pos[encID]--;
}
// JWP // tft.setTextColor(ST7735_WHITE);
// JWP // tft.setFont(OpenSans_16);
if (encID == 0)
{
// JWP // tft.fillRect(90, 100, 60, 20, ST7735_RED);
// JWP // tft.setCursor(100, 101);
}
else
{
// JWP // tft.fillRect(90, 150, 60, 20, ST7735_BLUE);
// JWP // tft.setCursor(100, 151);
}
// JWP // tft.print(Enc_Pos[encID]);
// JWP // tft.updateScreenAsyncT4();
}
lastClkState[encID] = currentClkState[encID];
old_GPIO1 = current_GPIO1;
}
}
// Setup -------------------------------------------------------
void setup(void)
{
Serial.begin(9600);
// Initializing the key/encoder MCP23017 I/O expander
mcp0.begin_I2C(0x21, &Wire1); // Adresse 0x20-0x27
mcp1.begin_I2C(0x22, &Wire1);
// Initialize Wire1 for encoder
Wire1.begin();
Wire1.setClock(400000UL); // I2C-Speed 400 kHz
// MPC23017(1-3) Expander for encoders & buttons
mcp0.setupInterrupts(true, false, LOW);
for (size_t i = 0; i < 16; i++)
{
mcp0.pinMode(i, INPUT_PULLUP);
mcp0.setupInterruptPin(i, CHANGE);
}
mcp0.getCapturedInterrupt();
mcp0.readGPIOAB();
mcp0.clearInterrupts();
mcp1.setupInterrupts(true, false, LOW);
for (size_t i = 0; i < 16; i++)
{
mcp1.pinMode(i, INPUT_PULLUP);
mcp1.setupInterruptPin(i, CHANGE);
}
mcp1.getCapturedInterrupt();
mcp1.readGPIOAB();
mcp1.clearInterrupts();
// init Key Interrupt
attachInterrupt(digitalPinToInterrupt(PIN_KEY_INT), Key_Interrupt, FALLING);
// init Encoder-Interrupt
attachInterrupt(digitalPinToInterrupt(PIN_ENC_INT), Encoder_Interrupt, FALLING);
}
void loop()
{
// Here are high-priority items
// lower priority here
if (loopCount++ > 15) // counter
{
//read_keys();
//read_ts();
read_enc();
loopCount = 0;
}
}
// MCP23017 Encoder query with acceleration
//
#include <Arduino.h>
#include <Wire.h>
#include <avr/interrupt.h>
#include <Adafruit_MCP23X17.h>
Adafruit_MCP23X17 mcp0; // Tasten 1-16
Adafruit_MCP23X17 mcp1; // Encoder
// Encoder-Variable
volatile uint16_t current_GPIO1 = 0;
uint16_t old_GPIO1 = 0;
int16_t Enc_Pos[7]= {0,0,0,0,0,0,0};
uint16_t currentClkState[7] = {0,0,0,0,0,0,0};
uint8_t Enc_B[7] = {0,0,0,0,0,0,0};
uint16_t lastClkState[7] = {0,0,0,0,0,0,0};
// macros and variables
#define PIN_KEY_INT (1)
#define PIN_ENC_INT (2)
bool key_action;
bool enc_action;
int loopCount;
// U10 MCP23017 3x Encoder Pin
#define enc1_A 256 // GPB0
#define enc1_B 512 // GPB1
#define enc2_A 1024 // GPB2
#define enc2_B 2048 // GPB3
#define enc3_A 4096 // GPB4
#define enc3_B 8192 // GPB5
// 7x Encoder
volatile uint16_t current_GPIO1 = 0;
uint16_t old_GPIO1 = 0;
int16_t Enc_Pos[7]= {0,0,0,0,0,0,0};
uint16_t currentClkState[7] = {0,0,0,0,0,0,0};
uint8_t Enc_B[7] = {0,0,0,0,0,0,0};
uint16_t lastClkState[7] = {0,0,0,0,0,0,0};
unsigned long lastInterruptTime = 0;
int accelerationFactor = 1;
// Key interrupt ----------------------------------------------
void Key_Interrupt()
{
key_action = true;
}
// Encoder-Interrupt ----------------------------------------------
void Encoder_Interrupt()
{
enc_action = true;
current_GPIO1 = mcp1.readGPIOAB();
}
// read Encoder ------------------------------------------------
void read_enc(void)
{
if (enc_action)
{
uint8_t encID = 0;
unsigned long interruptTime = millis();
unsigned long timeDiff = interruptTime - lastInterruptTime;
enc_action = false;
// Encoder Acceleration
// If the rotation is fast (< 50 ms), accelerate
if (timeDiff < 25)
{
accelerationFactor = 20;
}
else if (timeDiff < 50)
{
accelerationFactor = 5;
}
else
{
accelerationFactor = 1;
}
// Check MCP23017 GPIO for activity
uint16_t changesBits = old_GPIO1 ^ current_GPIO1;
// Encoder1 Clk Pin status
if (changesBits == enc1_A)
{
currentClkState[0] = bitRead(current_GPIO1, 8);
encID = 0;
} // Encode1 DT Pin status
else if (changesBits == enc1_B)
{
Enc_B[0] = bitRead(current_GPIO1, 9);
encID = 0;
}
// Encoder2 Clk Pin status
else if (changesBits == enc2_A)
{
currentClkState[1] = bitRead(current_GPIO1, 10);
encID = 1;
} // Encode2 DT Pin status
else if (changesBits == enc2_B)
{
Enc_B[1] = bitRead(current_GPIO1, 11);
encID = 1;
}
// Encoder3 Clk Pin status
else if (changesBits == enc3_A)
{
currentClkState[2] = bitRead(current_GPIO1, 12);
encID = 2;
} // Encode3 DT Pin status
else if (changesBits == enc3_B)
{
Enc_B[2] = bitRead(current_GPIO1, 13);
encID = 2;
}
// print encoder values
if (currentClkState[encID] != lastClkState[encID])
{
if (Enc_B[encID] != currentClkState[encID])
{
Enc_Pos[encID] += accelerationFactor;
if (Enc_Pos[encID] >= 1023)
{
Enc_Pos[encID] = 1023;
}
}
else
{
Enc_Pos[encID] -= accelerationFactor;
if (Enc_Pos[encID] <= 0)
{
Enc_Pos[encID] = 0;
}
}
// tft.setTextColor(ST7735_WHITE);
// tft.setFont(OpenSans_16);
if (encID == 0)
{
// tft.fillRect(90, 100, 60, 20, ST7735_RED);
// tft.setCursor(100, 101);
}
else if (encID == 1)
{
// tft.fillRect(90, 130, 60, 20, ST7735_BLUE);
// tft.setCursor(100, 131);
}
else if (encID == 2)
{
// tft.fillRect(90, 160, 60, 20, tab_color_green);
// tft.setCursor(100, 161);
}
// tft.print(Enc_Pos[encID]);
// tft.updateScreenAsyncT4();
}
lastClkState[encID] = currentClkState[encID];
old_GPIO1 = current_GPIO1;
lastInterruptTime = interruptTime;
}
}
// Setup -------------------------------------------------------
void setup(void)
{
Serial.begin(9600);
// Initializing the key/encoder MCP23017 I/O expander
mcp0.begin_I2C(0x21, &Wire1); // Adresse 0x20-0x27
mcp1.begin_I2C(0x22, &Wire1);
// Initialize Wire1 for encoder
Wire1.begin();
Wire1.setClock(400000UL); // I2C-Speed 400 kHz
// MPC23017(1-3) Expander for encoders & buttons
mcp0.setupInterrupts(true, false, LOW);
for (size_t i = 0; i < 16; i++)
{
mcp0.pinMode(i, INPUT_PULLUP);
mcp0.setupInterruptPin(i, CHANGE);
}
mcp0.getCapturedInterrupt();
mcp0.readGPIOAB();
mcp0.clearInterrupts();
mcp1.setupInterrupts(true, false, LOW);
for (size_t i = 0; i < 16; i++)
{
mcp1.pinMode(i, INPUT_PULLUP);
mcp1.setupInterruptPin(i, CHANGE);
}
mcp1.getCapturedInterrupt();
mcp1.readGPIOAB();
mcp1.clearInterrupts();
// init Key Interrupt
attachInterrupt(digitalPinToInterrupt(PIN_KEY_INT), Key_Interrupt, FALLING);
// init Encoder-Interrupt
attachInterrupt(digitalPinToInterrupt(PIN_ENC_INT), Encoder_Interrupt, FALLING);
}
void loop()
{
// Here are high-priority items
// lower priority here
if (loopCount++ > 15) // counter
{
//read_keys();
//read_ts();
read_enc();
loopCount = 0;
}
}
key_action and enc_action should be volatile