/***************************************************
This is our GFX example for the Adafruit ILI9341 Breakout and Shield
----> http://www.adafruit.com/products/1651
Check out the links above for our tutorials and wiring diagrams
These displays use SPI to communicate, 4 or 5 pins are required to
interface (RST is optional)
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
MIT license, all text above must be included in any redistribution
****************************************************/
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
//define screen pins
#define TFT_DC 9
#define TFT_CS 10
#define TFT_RST 8
#define TFT_MISO 12
#define TFT_MOSI 11
#define TFT_CLK 13
//define encoder pins
#define ENC_A 2
#define ENC_B 3
//define button pins
#define resetBtn 4
#define modeBtn 7
#define upBtn 5
#define downBtn 6
#define dbnce 20
#define holdTime 100
int ledState = LOW;
int resetBtnState;
int lastBtnState = LOW;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
unsigned long _lastIncReadTime = micros();
unsigned long _lastDecReadTime = micros();
int _pauseLength = 25000;
int _fastIncrement = 10;
int upBtnVal = 0;
int upBtnLast = 0;
long upBtnDnTime;
long upBtnUpTime;
boolean upignoreUp = false;
int downBtnVal = 0;
int downBtnLast = 0;
long downBtnDnTime;
long downBtnUpTime;
boolean downignoreUp = false;
int modeBtnVal = HIGH;
int modeBtnLast = 0;
unsigned long modeBtn_lastPress = 0;
unsigned long modeDebounce = 50;
int mode;
int gearRatio = 250;
volatile int counter = 0;
static int prevCount = 0;
int dir = 1;
int prevdir = 1;
int countdig[] = {0,0,0,0,0};
int prevdig[] = {0,0,0,0,0};
int digitpos[] = {75,110,145,190,225};
int x=0;
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);
void setup() {
// Set encoder pins and attach interrupts
pinMode(ENC_A, INPUT_PULLUP);
pinMode(ENC_B, INPUT_PULLUP);
pinMode(resetBtn, INPUT);
pinMode(upBtn, INPUT_PULLUP);
pinMode(downBtn, INPUT_PULLUP);
pinMode(modeBtn, INPUT_PULLUP);
//Attach interrupt for encoder
attachInterrupt(digitalPinToInterrupt(ENC_A), read_encoder, CHANGE);
attachInterrupt(digitalPinToInterrupt(ENC_B), read_encoder, CHANGE);
// Start the serial monitor to show output
Serial.begin(115200);
Serial.println("ILI9341 Test!");
tft.begin();
setScreen1();
}
void loop(void) {
//Read button states
upBtnVal = digitalRead(upBtn);
downBtnVal = digitalRead(downBtn);
int reading1 = digitalRead(modeBtn);
if (reading1 != modeBtnLast){
modeBtn_lastPress = millis();
}
if((millis()-modeBtn_lastPress) >= modeDebounce){
if (reading1 != modeBtnVal){
modeBtnVal = reading1;
if(modeBtnVal == HIGH){
mode = !mode;
Serial.println("Mode Changed");
if (mode == HIGH) {
Serial.println(" Mode 0");
tft.setCursor(0,48);
tft.setTextSize(1);
tft.fillRect(0,48,120,10,ILI9341_BLACK);
tft.print("Counter Mode");
tft.fillRect(0,220,300,10,ILI9341_BLACK);
}
else {
Serial.println(" Mode 1");
tft.setCursor(0,48);
tft.setTextSize(1);
tft.fillRect(0,48,120,10,ILI9341_BLACK);
tft.print("Counter Edit Mode");
tft.setCursor(0,220);
tft.print("Press +/- buttons to adjust the counter value");
}
}
}
}
modeBtnLast = reading1;
if (mode== HIGH) {
resetButton();
//Only print the counter value to the screeon if the value has changed. (LCD screens retain previously printed information)
if(counter != prevCount){
splitCounter();
splitPrevCounter();
updateCounterDisplay();
}
prevCount = counter;
}
else{ //mode button = LOW
// +/- button trigger function
buttonTrigger();
//Only print the counter value to the screeon if the value has changed. (LCD screens retain previously printed information)
if(counter != prevCount){
splitCounter();
splitPrevCounter();
updateCounterDisplay();
}
prevCount = counter;
}
}
void setScreen1(){ //display static screen elements
tft.setRotation(3);
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(0, 0);
tft.setTextColor(ILI9341_WHITE); tft.setTextSize(1);
tft.println(" Virginia Transformer Corp.");
tft.println();
tft.setTextColor(ILI9341_YELLOW); tft.setTextSize(2);
tft.println(" Winder #12");
tft.println();
tft.setTextColor(ILI9341_WHITE); tft.setTextSize(1);
tft.println("Counter Mode");
tft.println();
tft.setTextSize(5);
for(x=0; x < 5; x++){
tft.setCursor(digitpos[x], 104);
tft.setTextColor(ILI9341_WHITE);
tft.print(countdig[x]);
}
tft.setCursor(165,104);
tft.print('.');
tft.setCursor(40,104);
if(dir<0){
tft.print('-');
}
else{
tft.fillRect(40,104,25,40,ILI9341_BLACK);
}
}
void updateCounterDisplay(){ //Update dynamic elements
tft.setTextSize(5);
//Compare each digit to the value from the previous loop.
//The digit will only be redrawn if it has changed.
for(x=0; x < 5; x++){
if(countdig[x] != prevdig[x]){
//black out old value first.
//Draw digit in black over the top of previous white digit
tft.setCursor(digitpos[x], 104);
tft.setTextColor(ILI9341_BLACK);
tft.print(prevdig[x]);
//print new value in white
tft.setCursor(digitpos[x], 104);
tft.setTextColor(ILI9341_WHITE);
tft.print(countdig[x]);
tft.setCursor(40,104);
if(dir<0){
tft.print('-');
}
else{
tft.fillRect(40,104,25,40,ILI9341_BLACK);
}
}
}
}
//Function to split the counter
void splitCounter(){
//Split current counter value (considered maximum 5 digits)
if (counter>=0){
if (dir<0){
dir = (-1) * dir;
}
countdig[4] = dir * (counter%10);
countdig[3] = dir *((counter/10)%10);
countdig[2] = dir * ((counter/100)%10);
countdig[1] = dir * ((counter/1000)%10);
countdig[0] = dir * ((counter/10000)%10);
}
else{
if (dir>0){
dir = (-1) * dir;
}
countdig[4] = dir * (counter%10);
countdig[3] = dir *((counter/10)%10);
countdig[2] = dir * ((counter/100)%10);
countdig[1] = dir * ((counter/1000)%10);
countdig[0] = dir * ((counter/10000)%10);
}
}
//Function to split the previous counter
void splitPrevCounter(){
//Split previous counter value
if (prevCount>=0){
if (dir<0){
prevdir = (-1)*prevdir;
}
prevdig[4] = prevdir * (prevCount %10);
prevdig[3] = prevdir * ((prevCount / 10) %10);
prevdig[2] = prevdir * ((prevCount / 100) %10);
prevdig[1] = prevdir * ((prevCount / 1000) %10);
prevdig[0] = prevdir * ((prevCount / 10000) %10);
}
else{
if (dir>0){
prevdir = (-1)*prevdir;
}
prevdig[4] = prevdir * (prevCount %10);
prevdig[3] = prevdir * ((prevCount / 10) %10);
prevdig[2] = prevdir * ((prevCount / 100) %10);
prevdig[1] = prevdir * ((prevCount / 1000) %10);
prevdig[0] = prevdir * ((prevCount / 10000) %10);
}
}
// Encoder reading code
void read_encoder() {
// Encoder interrupt routine for both pins. Updates counter
// if they are valid and have rotated a full indent
static uint8_t old_AB = 3; // Lookup table index
static int8_t encval = 0; // Encoder value
static const int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0}; // Lookup table
old_AB <<=2; // Remember previous state
if (digitalRead(ENC_A)) old_AB |= 0x02; // Add current state of pin A
if (digitalRead(ENC_B)) old_AB |= 0x01; // Add current state of pin B
encval += enc_states[( old_AB & 0x0f )];
// Update counter if encoder has rotated a full indent, that is at least 4 steps
if( encval > 3 ) { // Four steps forward
int changevalue = 1;
if((micros() - _lastIncReadTime) < _pauseLength) {
changevalue = _fastIncrement * changevalue;
}
_lastIncReadTime = micros();
counter = counter + changevalue; // Update counter
encval = 0;
}
else if( encval < -3 ) { // Four steps backward
int changevalue = -1;
if((micros() - _lastDecReadTime) < _pauseLength) {
changevalue = _fastIncrement * changevalue;
}
_lastDecReadTime = micros();
counter = counter + changevalue; // Update counter
encval = 0;
}
}
// Reset Button code
void resetButton(){
// read the state of the switch into a local variable:
int reading = digitalRead(resetBtn);
// check to see if you just pressed the button
// (i.e. the input went from LOW to HIGH), and you've waited long enough
// since the last press to ignore any noise:
// If the switch changed, due to noise or pressing:
if (reading != lastBtnState) {
// reset the debouncing timer
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer than the debounce
// delay, so take it as the actual current state:
// if the button state has changed:
if (reading != resetBtnState) {
resetBtnState = reading;
// only toggle the LED if the new button state is HIGH
if (resetBtnState == HIGH) {
counter = 0;
tft.fillRect(40,104,250,50,ILI9341_BLACK);
tft.setTextSize(5);
for(x=0; x < 5; x++){
tft.setCursor(digitpos[x], 104);
tft.setTextColor(ILI9341_WHITE);
tft.print(countdig[x]);
}
tft.setCursor(165,104);
tft.print('.');
}
}
}
// save the reading. Next time through the loop, it'll be the lastButtonState:
lastBtnState = reading;
}
// +/- buttons code
void buttonTrigger(){
// Test for up button pressed and store the down time
if (upBtnVal == LOW && upBtnLast == HIGH && (millis() - upBtnUpTime) > long(dbnce)){
upBtnDnTime = millis();
}
// Test for up button release and store the up time
if (upBtnVal == HIGH && upBtnLast == LOW && (millis() - upBtnDnTime) > long(dbnce)){
if (upignoreUp == false) event1();
else upignoreUp = false;
upBtnUpTime = millis();
}
// Test for up button held down for longer than the hold time
if (upBtnVal == LOW && (millis() - upBtnDnTime) > long(holdTime)){
event2();
upignoreUp = true;
upBtnDnTime = millis();
}
// Test for down button pressed and store the down time
if (downBtnVal == LOW && downBtnLast == HIGH && (millis() - downBtnUpTime) > long(dbnce)){
downBtnDnTime = millis();
}
// Test for down button release and store the up time
if (downBtnVal == HIGH && downBtnLast == LOW && (millis() - downBtnDnTime) > long(dbnce)){
if (downignoreUp == false) event3();
else downignoreUp = false;
downBtnUpTime = millis();
}
// Test for down button held down for longer than the hold time
if (downBtnVal == LOW && (millis() - downBtnDnTime) > long(holdTime)){
event4();
downignoreUp = true;
downBtnDnTime = millis();
}
upBtnLast = upBtnVal;
downBtnLast = downBtnVal;
}
void event1(){
//Slow increment function short press interval
counter = counter + 1;
}
void event2(){
//Fast increment function long press interval
counter = counter + 50;
}
void event3(){
//Slow decrement function short press interval
counter = counter - 1;
}
void event4(){
//Fast decrement function long press interval
counter = counter - 50;
}