Creating a GUI of sorts - Teensy 3.1 and 2.2" ILI9341 Display

Status
Not open for further replies.

nickssss

Member
Hey all... round two of questions

Here's a synopsis of my design:

I'm creating a MIDI controllable guitar pedal. Ideally, I'll have my void loop running as quickly as possible to keep up with / process any incoming MIDI signals (program change and CC messages). I would like to have visual feedback on my LCD display as the program is running (for example, if there are no incoming MIDI messages it will show the currently selected preset, if there is a program change the number on the display will update accordingly). Later on, I'll be implementing a rotary encoder to scroll through a menu to change any options I need to.

The first (expected) problem that arrises is that my display will constantly refresh with the loop. I am hesitant to add a delay inside any of the TFT functions because I don't want to slow down the MIDI read process. I've tried a couple iterations of while and do while loops to try and solve the problem but to no avail. My current code is below(I do have a delay in the main loop just so I don't die from the strobe effect). In essence, I want the MIDI.read() function to constantly be waiting for an input while I have a steady output to my display.

My intuition tells me that interrupts will have to be implemented somehow, but I'm not sure quite how to start with such an endeavour. Any guidance would be heartily appreciated!



Code:
#include "SPI.h"
#include "ILI9341_t3.h"
#include <Wire.h>
#include <EEPROM.h>
#include <MIDI.h>
#include <midi_Defs.h>
#include <midi_Message.h>
#include <midi_Namespace.h>
#include <midi_Settings.h>


MIDI_CREATE_INSTANCE(HardwareSerial, Serial3, MIDI);  // create an instance of MIDI using hardware serial serial 3 port

 struct Preset{
  byte lOhm;
  byte lWet;
  byte rOhm;
  byte rWet;
};

// MIDI Function Prototypes

void PresetStore(struct Preset pToWrite, int presetNum);
struct Preset PresetRead(int presetNum);
void GlobalSettings();


// For the Adafruit shield, these are the default.
#define TFT_DC 9
#define TFT_CS 10

// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC);
// If using the breakout, change pins as desired
//Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);



void setup() {
  Serial.begin(9600);
  
  // MIDI Setup
  MIDI.setHandleProgramChange(DealWithProgramChange);
  MIDI.setHandleControlChange(DealWithControlChange);
  MIDI.begin(MIDI_CHANNEL_OMNI);
  
  // ILI9341 Setup
  Serial.println("ILI9341 Test!"); 
  tft.begin();

  // read diagnostics (optional but can help debug problems)
  uint8_t x = tft.readcommand8(ILI9341_RDMODE);
  Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDMADCTL);
  Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDPIXFMT);
  Serial.print("Pixel Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDIMGFMT);
  Serial.print("Image Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDSELFDIAG);
  Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX); 
  
  Serial.println(F("Benchmark                Time (microseconds)"));

  Serial.print(F("Screen fill              "));
  Serial.println(testFillScreen());
  delay(500);

}

// MAIN LOOP

void loop(void) {
  
  while(MIDI.read() == 0)
   { 
     presetScreen();
     delay(10000);
   }
 
  }


// DISPLAY FUNCTIONS

unsigned long testFillScreen() {
  unsigned long start = micros();
  tft.fillScreen(ILI9341_BLACK);
  tft.fillScreen(ILI9341_RED);
  tft.fillScreen(ILI9341_GREEN);
  tft.fillScreen(ILI9341_BLUE);
  tft.fillScreen(ILI9341_BLACK);
  return micros() - start;
}

unsigned long testText() {
  tft.fillScreen(ILI9341_BLACK);
  unsigned long start = micros();
  tft.setCursor(0, 0);
  tft.setTextColor(ILI9341_WHITE);  tft.setTextSize(1);
  tft.println("Hello World!");
  tft.setTextColor(ILI9341_YELLOW); tft.setTextSize(2);
  tft.println(1234.56);
  tft.setTextColor(ILI9341_RED);    tft.setTextSize(3);
  tft.println(0xDEADBEEF, HEX);
  tft.println();
  tft.setTextColor(ILI9341_GREEN);
  tft.setTextSize(5);
  tft.println("Groop");
  tft.setTextSize(2);
  tft.println("I implore thee,");
  tft.setTextSize(1);
  tft.println("my foonting turlingdromes.");
  tft.println("And hooptiously drangle me");
  tft.println("with crinkly bindlewurdles,");
  tft.println("Or I will rend thee");
  tft.println("in the gobberwarts");
  tft.println("with my blurglecruncheon,");
  tft.println("see if I don't!");
  return micros() - start;
}


unsigned long presetScreen(){
  tft.fillScreen(0xD6EBFF);
  unsigned long start = micros();
  tft.setCursor(20, 25);;
  tft.setRotation(1);
  tft.setTextColor(ILI9341_BLUE);  tft.setTextSize(7);
  tft.println("Preset");
  tft.setCursor(197, 100);
  tft.setTextSize(6);
  tft.println("xx");
}


// MIDI FUNCTIONALITY
// Program Change Handler

void DealWithProgramChange(byte channel, byte number)
{
  int ch, bank;
  
  ch = MIDI.getChannel();
  bank = MIDI.getData1();
  
  Serial.println(String("Program change") + bank + "on channel" + ch + "received!");
 
}

// Control Change Handler

void DealWithControlChange(byte channel, byte number, byte value)
{
  int ch, param, ccValue;
  
  ch = MIDI.getChannel();
  param = MIDI.getData1();
  ccValue = MIDI.getData2();
  
  Serial.println(String("Control change param of ") + param + "on channel" + ch + "with value of" + ccValue + "received!");

}
 
Instead of refreshing the screen constantly, use a variable to track if anything has changed. Only update the screen if there has been a change.
 
What are you drawing to the screen? Simple text and lines are drawn very quickly. Bitmaps can take a little longer. I would remove or reduce the microdelays in adafruits library because they were written for slow Arduino.

Also remember that USB has buffer space on both ends so you wont be losing data easily.

Have you built or tested any of this yet? How does it behave?
 
Success Nantonos, thank you!

For future reference, I made the following changes to my code:

Code:
// defined two global variables that can be modified by any function

byte prevPreset = 0;
byte curPreset = 0;

// added the following to void setup() to start the screen
presetScreen(0);

// changed void loop() to the following
void loop(void) {
  
  MIDI.read();
  
  if(prevPreset != curPreset)
    presetScreen(curPreset);
  else;
  
  prevPreset = curPreset;
}

// changed the argument for the default preset screen to unsigned int from void
unsigned long presetScreen(unsigned int preset){
  tft.fillScreen(0xD6EBFF);
  unsigned long start = micros();
  tft.setCursor(20, 25);;
  tft.setRotation(1);
  tft.setTextColor(ILI9341_BLUE);  tft.setTextSize(7);
  tft.println("Preset");
  tft.setCursor(197, 100);
  tft.setTextSize(6);
  tft.println(preset);
}

// modified my program change handler to modify curPreset when a program change is received
void DealWithProgramChange(byte channel, byte number)
{
  int ch, bank;
  
  ch = MIDI.getChannel();
  bank = MIDI.getData1();
  
  Serial.println(String("Program change") + bank + "on channel" + ch + "received!");
 
  curPreset = bank; 
}

Until next time,

Nick
 
Status
Not open for further replies.
Back
Top