kluger
Published © GPL3+

USB Media Controller

Control music playback and volume with touchscreen LCD

IntermediateShowcase (no instructions)931
USB Media Controller

Things used in this project

Hardware components

Arduino Leonardo
Arduino Leonardo
×1
2.4 inch TFT display with touchscreen
×1
Case, plastic
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Schematics

assembly

Its just a LCD plugged into a Leonardo, the Leonardo is in a case that allows access to the connetors

Assembly

Code

music_control_LCD

Arduino
Controls LCD display, reads touchscreen position, and communicates over USB
//Most of this code is from here:
//https://gist.github.com/calogerus/79ef0c4cf04d9ea33dae9fd77a3a7316#file-ili9341_8-ino
//The ability to draw (ASCII) characters is still in this code, but not used in my application.
//and here:
//https://uboopenfactory.univ-brest.fr/Les-Labs/MusicLab/Projets/Arduino-Media-Keys
//This is for the parallel port LCD 
// Connect data pins LCD_D 0-7 to arduino Leonardo:
// LCD_D 0 -- D8 PB4
// LCD_D 1 -- D9 PB5
// LCD_D 2 -- D2 PD1
// LCD_D 3 -- D3 PD0
// LCD_D 4 -- D4 PD4
// LCD_D 5 -- D5 PC6
// LCD_D 6 -- D6 PD7
// LCD_D 7 -- D7 PE6
// Connect command pins:
// LCD_RST -- A4   PF1 1 -> 0 min 15 micros 0 -> 1 
// LCD_CS  -- A3   PF4 chip select, aktiv LOW
// LCD_RS  -- A2   PF5 data/command select, 0 command, 1 data
// LCD_WR  -- A1   PF6 -> 1, HIGH when not used
// LCD_RD  -- A0   PF7 -> 1, HIGH when not used
//This includes media keyboard commands and mouse outputs
#include "HID-Project.h"

#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF


// Touchscreen connection:
// Used MCU_Friend library example 'diagnose_Touchpins' on a MEGA 2560 to discover the pins used for the touchscreen
// (the pins are multiplexed with LCD control pins)
// MCU_Friend does not fit on a Leonardo 
#define Y1 A3  //PF4 need two analog inputs
#define X2 A2   //PB4 
#define Y2 9   //
#define X1 8  //  

int16_t P_COL=0; // LCD cursor pointer
int16_t P_ROW=0;
int16_t T_COL=0; // TOUCHSCREEN(TS) detected value
int16_t T_ROW=0;

// TS calibration
uint16_t ROW_F=157; // TS first row
uint16_t ROW_L=880; // TS last row
uint16_t COL_F=116; // TS first column
uint16_t COL_L=895; // TS last column

uint8_t F_SIZE=3; // font size
uint16_t F_COLOR=WHITE; // foreground color
uint16_t B_COLOR=0x0C0C; // background color

// draw keypad
String K_LABEL[] = {"1","2","3","4","5","6","7","8","9","0","<"};
uint16_t K_ROW[]  = {150,150,150,100,100,100,50,50,50,200,200};
uint16_t K_COL[]  = {10,50,90,10,50,90,10,50,90,50,90};

void LCD_write(uint8_t d) {
  //all of the LCD interface is very specific to the Leonardo
  // ILI9341 reads data pins when WR rises from LOW to HIGH (A1 pin on arduino)
  PORTF = PORTF & B10111111; // WR 0
  // data pins of ILI9341 connected to four arduino ports
  PORTD = (PORTD & ~B10010011) | (((d) & B01000000) << 1) | // LCD_D 6 -- D6 PD7
                                  ((d) & B00010000) |       // LCD_D 4 -- D4 PD4
                                 (((d) & B00001000) >> 3) | // LCD_D 3 -- D3 PD0
                                 (((d) & B00000100) >> 1);  // LCD_D 2 -- D2 PD1
  PORTB = (PORTB & ~B00110000) | (((d) & B00000011) << 4);  // LCD_D 0 -- D8 PB4
                                                            // LCD_D 1 -- D9 PB5
  PORTC = (PORTC & ~B01000000) | (((d) & B00100000) << 1);  // LCD_D 5 -- D5 PC6
  PORTE = (PORTE & ~B01000000) | (((d) & B10000000) >> 1);  // LCD_D 7 -- D7 PE6
  
  PORTF = PORTF | B01000000; // WR 1
}

void LCD_command_write(uint8_t d) {
  PORTF = PORTF & B11011111; // LCD_RS = 0, arduino pin A2
  // write data pins
  LCD_write(d);
}

void LCD_data_write(uint8_t d) {
  PORTF = PORTF | B00100000; // LCD_RS = 1, arduino pin A2
  // write data pins
  LCD_write(d);
}

uint8_t LCD_read(void) {
  //this doesn't work
  // CS LOW, WR HIGH, RD HIGH->LOW>HIGH, RS(D/C) HIGH 
  PORTF = PORTF | B00100000; // LCD_RS = 1, arduino pin A2
 
  BD_as_input(); // Set arduino pins as input
  // LCD_RD - arduino pin A0
  // After RD falls from HIGH to LOW ILI9341 outputs data until RD returns to HIGH
  PORTF = PORTF & B01111111; // RD 0
 
  uint8_t bit6432 = PIND; // Read data pins 7410
  bit6432 = ((bit6432 & B10000000)>>1) |  // LCD_D 6 -- D6 PD7 
             (bit6432 & B00010000) |      // LCD_D 4 -- D4 PD4
            ((bit6432 & B00000010)<<1) |  // LCD_D 2 -- D2 PD1
            ((bit6432 & B00000001)<<3);   // LCD_D 3 -- D3 PD0
  uint8_t bit10 = (PINB & B00110000) >> 4;// LCD_D 0 -- D8 PB4 
                                          // LCD_D 1 -- D9 PB5
  uint8_t bit5 = (PINC & B01000000) >> 1; // LCD_D 5 -- D5 PC6
  uint8_t bit7 = (PINE & B01000000) << 1; // LCD_D 7 -- D7 PE6

  PORTF = PORTF | B10000000; // RD 1
  BD_as_output(); // Re-Set arduino pins as output
  return (bit6432 | bit10 | bit5 | bit7);
}

void BD_as_input(void) {
  // 
  DDRD = DDRD & ~B10010011; 
  DDRB = DDRB & ~B00110000; 
  DDRC = DDRC & ~B01000000;
  DDRE = DDRC & ~B01000000;
}

void BD_as_output(void) {
  DDRD = DDRD | B10010011; 
  DDRB = DDRB | B00110000; 
  DDRC = DDRC | B01000000;
  DDRE = DDRC | B01000000;
}

void LCD_init(void) {
  // LCD_RESET 1 - 0 - 1, arduino pin A4
  DDRF = DDRF | 11110010;
  PORTF = PORTF | B11110010; // 1
  delay(10);
  PORTF = PORTF & B11111101; // 0
  delay(20);
  PORTF = PORTF | B00000010; // 1
  delay(20);
  
  // CS HIGH, WR HIGH, RD HIGH, CS LOW
  PORTF = PORTF | B11110010; // CS 1 WR 1 RD 1
  delay(1);
  PORTF = PORTF & B11101111; // CS 0
  
  LCD_command_write(0xF7); // Pump ratio control
  LCD_data_write(0x20); // 
  
  LCD_command_write(0x3A); // COLMOD: Pixel Format Set
  LCD_data_write(0x55); 
  
  LCD_command_write(0x36); // Memory Access Control 
  // MY  - Row Address Order (bit7)
  // MX  - Column Address Order
  // MV  - Row / Column Exchange
  // ML  - Vertical Refresh Order
  // BGR - RGB-BGR Order
  // MH  - Horizontal Refresh ORDER(bit2)
  LCD_data_write(B00001000); 
  
  LCD_command_write(0x11); // Sleep OUT
  LCD_command_write(0x29); // Display ON
  
  delay(50);
  LCD_command_write(0xD3); // Read ID, doesn't work
  LCD_read(); 
  LCD_read();
  LCD_read();
  LCD_read();
}

void LCD_rect(int16_t col,int16_t row, int16_t width, int16_t height, int16_t color) {
  
  LCD_command_write(0x2a); // Column Address Set
  LCD_data_write(row>>8);
  LCD_data_write(row);
  LCD_data_write((row+height-1)>>8);
  LCD_data_write(row+height-1);
  LCD_command_write(0x2b); // Page Address Set
  LCD_data_write(col>>8); 
  LCD_data_write(col);
  LCD_data_write((col+width-1)>>8);
  LCD_data_write(col+width-1);
  LCD_command_write(0x2c); // Memory Write
 
  byte chigh=color >> 8;
  byte clow=color;
  int i,j;
  for(i=0;i<width;i++)
    for(j=0;j<height;j++)
    {
      LCD_data_write(chigh);
      LCD_data_write(clow);
    }
}
/*
 * This routine draws equalateral triangles 'pointed' left or right
 * it uses the y = mx + b line formula to determine if points are inside the two lines
 * the slope m is alway 0.5
 */
void LCD_triangle(int16_t col,int16_t row, int16_t width, int16_t height, int16_t color, bool left) {
  bool inside = false;
  LCD_command_write(0x2a); // Column Address Set
  LCD_data_write(row>>8);
  LCD_data_write(row);
  LCD_data_write((row+height-1)>>8);
  LCD_data_write(row+height-1);
  LCD_command_write(0x2b); // Page Address Set
  LCD_data_write(col>>8); 
  LCD_data_write(col);
  LCD_data_write((col+width-1)>>8);
  LCD_data_write(col+width-1);
  LCD_command_write(0x2c); // Memory Write
  byte bhigh = B_COLOR >> 8;
  byte blow =  B_COLOR;
  byte chigh=color >> 8;
  byte clow=color;
  int i,j;
  for(i=0;i<width;i++)
    for(j=0;j<height;j++)
    {
      if (left) {
        inside = (j <= ((i * 0.5) + (height / 2.0))) && (j >= ((height / 2.0) - (i * .5)));
      } else inside = (j >= (i * 0.5)) && (j <= (height - (i * .5)));
      if (inside){
        LCD_data_write(chigh);
        LCD_data_write(clow);
      }else {
        LCD_data_write(bhigh);
        LCD_data_write(blow);
      }
    }
}

void LCD_clear(byte color) {
  /* 
  Accelerate screen clearing sacrifing color depth. Instead of writing
  to data bits high and low byte of the color for each pixel, which takes more 
  than 300ms to fill the screen, set once data bits to 0's for black or 
  to 1's for white and start changing control bit WR from LOW to HIGH to 
  write whole area. It takes cca 70 ms. In this way the color of screen are
  limited to those with the same high and low byte. For example setting color
  to 0x0C fills the screen with color 0x0C0C.
  Writing two pixels in one cycle lowering cycle count from 76800 (240x320) to 
  38400 clears screen in less then 30ms.
  */
  
  LCD_command_write(0x2a); 
  LCD_data_write(0);
  LCD_data_write(0);
  LCD_data_write(0);
  LCD_data_write(0xEC);
  LCD_command_write(0x2b); 
  LCD_data_write(0); 
  LCD_data_write(0);
  LCD_data_write(1);
  LCD_data_write(0x3F);
  LCD_command_write(0x2c);
  
  PORTF = PORTF | B00100000; //  LCD_RS = 1, arduino pin A2 

  PORTD = (PORTD & ~B10010011) | (((color) & B01000000) << 1) | 
                                  ((color) & B00010000) | 
                                 (((color) & B00001000) >> 3) | 
                                 (((color) & B00000100) >> 1); 
  PORTB = (PORTB & ~B00110000) | (((color) & B00000011) << 4); 
  PORTC = (PORTC & ~B01000000) | (((color) & B00100000) << 1);
  PORTE = (PORTE & ~B01000000) | (((color) & B10000000) >> 1);
  
  uint16_t x;
  x=38400; // 240*320/2PORTF = ; // WR 0
  byte wr0= PORTF & B10111111; // set WR 0
  byte wr1= PORTF | B01000000; // set WR 1
  for(uint16_t y=0;y<x;y++)
  {
    PORTF = wr0;
    PORTF = wr1;
    PORTF = wr0;
    PORTF = wr1;
    
    PORTF = wr0;
    PORTF = wr1;
    PORTF = wr0;
    PORTF = wr1;
  }
}

void Display_integer(int16_t n) {
  String str=String(n);
  byte l=str.length(); 
  char b[l+1]; // +1 for the null terminator
  str.toCharArray(b,l+1);
  for(int n=0; n<l; n++) {
    Display_char(b[n]);
  }
}

void Display_string(String str) {
  byte l=str.length(); 
  char b[l+1]; // +1 for the null terminator
  str.toCharArray(b,l+1);
  for(int n=0; n<l; n++) {
    Display_char(b[n]);
  }
}

void Display_char(char znak) {
  static const byte ASCII[][5] =
  {
    {0x00, 0x00, 0x00, 0x00, 0x00}, // 20
    {0x00, 0x00, 0x5f, 0x00, 0x00}, // 21 ! 
    {0x00, 0x07, 0x00, 0x07, 0x00}, // 22 "
    {0x14, 0x7f, 0x14, 0x7f, 0x14}, // 23 # 
    {0x24, 0x2a, 0x7f, 0x2a, 0x12} ,// 24 $
    {0x23, 0x13, 0x08, 0x64, 0x62}, // 25 %
    {0x36, 0x49, 0x55, 0x22, 0x50}, // 26 &
    {0x00, 0x00, 0x07, 0x05, 0x07}, // 27 ' 
    {0x00, 0x1c, 0x22, 0x41, 0x00}, // 28 (
    {0x00, 0x41, 0x22, 0x1c, 0x00}, // 29 )
    {0x14, 0x08, 0x3e, 0x08, 0x14}, // 2a *
    {0x08, 0x08, 0x3e, 0x08, 0x08}, // 2b +
    {0x00, 0x50, 0x30, 0x00, 0x00}, // 2c ,
    {0x08, 0x08, 0x08, 0x08, 0x08}, // 2d -
    {0x00, 0x60, 0x60, 0x00, 0x00}, // 2e .
    {0x20, 0x10, 0x08, 0x04, 0x02}, // 2f /
    {0x3e, 0x51, 0x49, 0x45, 0x3e}, // 30 0
    {0x00, 0x42, 0x7f, 0x40, 0x00}, // 31 1
    {0x42, 0x61, 0x51, 0x49, 0x46}, // 32 2
    {0x21, 0x41, 0x45, 0x4b, 0x31}, // 33 3
    {0x18, 0x14, 0x12, 0x7f, 0x10}, // 34 4
    {0x27, 0x45, 0x45, 0x45, 0x39}, // 35 5
    {0x3c, 0x4a, 0x49, 0x49, 0x30}, // 36 6
    {0x01, 0x71, 0x09, 0x05, 0x03}, // 37 7
    {0x36, 0x49, 0x49, 0x49, 0x36}, // 38 8
    {0x06, 0x49, 0x49, 0x29, 0x1e}, // 39 9
    {0x00, 0x36, 0x36, 0x00, 0x00}, // 3a :
    {0x00, 0x56, 0x36, 0x00, 0x00}, // 3b ;
    {0x08, 0x14, 0x22, 0x41, 0x00}, // 3c <
    {0x14, 0x14, 0x14, 0x14, 0x14}, // 3d =
    {0x00, 0x41, 0x22, 0x14, 0x08}, // 3e >
    {0x02, 0x01, 0x51, 0x09, 0x06}, // 3f ?
    {0x32, 0x49, 0x79, 0x41, 0x3e}, // 40 @
    {0x7e, 0x11, 0x11, 0x11, 0x7e}, // 41 A
    {0x7f, 0x49, 0x49, 0x49, 0x36}, // 42 B
    {0x3e, 0x41, 0x41, 0x41, 0x22}, // 43 C
    {0x7f, 0x41, 0x41, 0x22, 0x1c}, // 44 D
    {0x7f, 0x49, 0x49, 0x49, 0x41}, // 45 E
    {0x7f, 0x09, 0x09, 0x09, 0x01}, // 46 F
    {0x3e, 0x41, 0x49, 0x49, 0x7a}, // 47 G
    {0x7f, 0x08, 0x08, 0x08, 0x7f}, // 48 H
    {0x00, 0x41, 0x7f, 0x41, 0x00}, // 49 I
    {0x20, 0x40, 0x41, 0x3f, 0x01}, // 4a J
    {0x7f, 0x08, 0x14, 0x22, 0x41}, // 4b K
    {0x7f, 0x40, 0x40, 0x40, 0x40}, // 4c L
    {0x7f, 0x02, 0x0c, 0x02, 0x7f}, // 4d M
    {0x7f, 0x04, 0x08, 0x10, 0x7f}, // 4e N
    {0x3e, 0x41, 0x41, 0x41, 0x3e}, // 4f O
    {0x7f, 0x09, 0x09, 0x09, 0x06}, // 50 P
    {0x3e, 0x41, 0x51, 0x21, 0x5e}, // 51 Q
    {0x7f, 0x09, 0x19, 0x29, 0x46}, // 52 R
    {0x46, 0x49, 0x49, 0x49, 0x31}, // 53 S
    {0x01, 0x01, 0x7f, 0x01, 0x01}, // 54 T
    {0x3f, 0x40, 0x40, 0x40, 0x3f}, // 55 U
    {0x1f, 0x20, 0x40, 0x20, 0x1f}, // 56 V
    {0x3f, 0x40, 0x38, 0x40, 0x3f}, // 57 W
    {0x63, 0x14, 0x08, 0x14, 0x63}, // 58 X
    {0x07, 0x08, 0x70, 0x08, 0x07}, // 59 Y
    {0x61, 0x51, 0x49, 0x45, 0x43}, // 5a Z
    {0x00, 0x7f, 0x41, 0x41, 0x00}, // 5b [
    {0x02, 0x04, 0x08, 0x10, 0x20}, // 5c Y
    {0x00, 0x41, 0x41, 0x7f, 0x00}, // 5d ]
    {0x04, 0x02, 0x01, 0x02, 0x04}, // 5e ^
    {0x40, 0x40, 0x40, 0x40, 0x40}, // 5f _
    {0x00, 0x01, 0x02, 0x04, 0x00}, // 60 `
    {0x20, 0x54, 0x54, 0x54, 0x78}, // 61 a
    {0x7f, 0x48, 0x44, 0x44, 0x38}, // 62 b
    {0x38, 0x44, 0x44, 0x44, 0x20}, // 63 c
    {0x38, 0x44, 0x44, 0x48, 0x7f}, // 64 d
    {0x38, 0x54, 0x54, 0x54, 0x18}, // 65 e
    {0x08, 0x7e, 0x09, 0x01, 0x02}, // 66 f
    {0x0c, 0x52, 0x52, 0x52, 0x3e}, // 67 g
    {0x7f, 0x08, 0x04, 0x04, 0x78}, // 68 h
    {0x00, 0x44, 0x7d, 0x40, 0x00}, // 69 i
    {0x20, 0x40, 0x44, 0x3d, 0x00}, // 6a j
    {0x7f, 0x10, 0x28, 0x44, 0x00}, // 6b k
    {0x00, 0x41, 0x7f, 0x40, 0x00}, // 6c l
    {0x7c, 0x04, 0x18, 0x04, 0x78}, // 6d m
    {0x7c, 0x08, 0x04, 0x04, 0x78}, // 6e n
    {0x38, 0x44, 0x44, 0x44, 0x38}, // 6f o
    {0x7c, 0x14, 0x14, 0x14, 0x08}, // 70 p
    {0x08, 0x14, 0x14, 0x18, 0x7c}, // 71 q
    {0x7c, 0x08, 0x04, 0x04, 0x08}, // 72 r
    {0x48, 0x54, 0x54, 0x54, 0x20}, // 73 s
    {0x04, 0x3f, 0x44, 0x40, 0x20}, // 74 t
    {0x3c, 0x40, 0x40, 0x20, 0x7c}, // 75 u
    {0x1c, 0x20, 0x40, 0x20, 0x1c}, // 76 v
    {0x3c, 0x40, 0x30, 0x40, 0x3c}, // 77 w
    {0x44, 0x28, 0x10, 0x28, 0x44}, // 78 x
    {0x0c, 0x50, 0x50, 0x50, 0x3c}, // 79 y
    {0x44, 0x64, 0x54, 0x4c, 0x44}, // 7a z
    {0x00, 0x08, 0x36, 0x41, 0x00}, // 7b {
    {0x00, 0x00, 0x7f, 0x00, 0x00}, // 7c |
    {0x00, 0x41, 0x36, 0x08, 0x00}, // 7d }
    {0x10, 0x08, 0x08, 0x10, 0x08}, // 7e 
    {0x00, 0x06, 0x09, 0x09, 0x06}  // 7f 
  };  
  
  int8_t size=F_SIZE;
  int16_t color=F_COLOR;
  int16_t bcolor=B_COLOR;
  
  if( (P_COL+(size*6)) > 319) {
    P_COL=0;
    P_ROW+=size*(8+1);
  }
  
  LCD_command_write(0x2a); // ROWS
  LCD_data_write(P_ROW>>8);
  LCD_data_write(P_ROW);
  LCD_data_write(((P_ROW+size*8)-1)>>8);
  LCD_data_write((P_ROW+size*8)-1);
  LCD_command_write(0x2b); // COLUMNS
  LCD_data_write(P_COL>>8); 
  LCD_data_write(P_COL);
  LCD_data_write((P_COL+(size*6))>>8);
  LCD_data_write(P_COL+(size*6));
  LCD_command_write(0x2c);
  byte bchigh=bcolor >> 8;
  byte bclow=bcolor;
  byte fchigh=color >> 8;
  byte fclow=color;
  byte index, nbit, i, j;
  for (index = 0; index < 5; index++) {    
    char col=ASCII[znak - 0x20][index];
    for ( i=0; i<size; i++){
      byte mask=B00000001;
      for (nbit = 0; nbit < 8; nbit++) {
        if (col & mask) {
          for (j=0; j<size; j++){
            LCD_data_write(fchigh);
            LCD_data_write(fclow);
          }
        }
        else {
          for (j=0; j<size; j++){
            LCD_data_write(bchigh);
            LCD_data_write(bclow);
          }
        }
        mask=mask<<1;
      }
    }
  }
  P_COL+=size*6;  
}

void Display_clear_char(byte n) {
  // delete n chars
  int8_t size=F_SIZE;
  int16_t bcolor=B_COLOR;
 
  LCD_command_write(0x2a); // ROWS
  LCD_data_write(P_ROW>>8);
  LCD_data_write(P_ROW);
  LCD_data_write(((P_ROW+size*8)-1)>>8);
  LCD_data_write((P_ROW+size*8)-1);
  LCD_command_write(0x2b); // COLUMNS
  LCD_data_write(P_COL>>8); 
  LCD_data_write(P_COL);
  LCD_data_write((P_COL+(size*6*n))>>8);
  LCD_data_write(P_COL+(size*6*n));
  LCD_command_write(0x2c);
  
  byte bchigh=bcolor >> 8;
  byte bclow=bcolor;
  int16_t cyc=size*8 * size*6*n;
  for (int16_t i=0; i<cyc; i++) {
    LCD_data_write(bchigh);
    LCD_data_write(bclow);
  }
}

byte ReadTouch(void) {
  //Y1 A3  A2
  //X1 A2  A1
  //Y2 9   6
  //X2 8   7
  int16_t row, col;
  int8_t touch, wait_touch, valid;
  wait_touch=1;
  valid=0;
  PORTF = PORTF | B00010000; // CS 1
  while (wait_touch) {
    pinMode(Y1, INPUT); 
    pinMode(Y2, INPUT_PULLUP); 
    
    pinMode(X1, OUTPUT);
    pinMode(X2, OUTPUT);
    digitalWrite(X1, LOW);
    digitalWrite(X2, LOW);
    
    touch = !digitalRead(Y1); // 0 - touched
    if (touch) {
      //delay(5);
      digitalWrite(X1, HIGH);   // X variant A
      //digitalWrite(X2, HIGH);   // X variant B
      delay(1);
      row = analogRead(Y1);
      delay(4); 
      if (abs(analogRead(Y1)-row)>3) { return 0;}
      delay(3);
      if (abs(analogRead(Y1)-row)>3) { return 0;}
      //if (analogRead(Y1)!=row) { return 0;}
      
      pinMode(X1, INPUT); 
      pinMode(X2, INPUT_PULLUP); 
      
      pinMode(Y1, OUTPUT);
      pinMode(Y2, OUTPUT);
      //digitalWrite(Y1, HIGH);  // Y variant A
      //digitalWrite(Y2, LOW);  // Y variant A
      digitalWrite(Y1, LOW);  // Y variant B
      digitalWrite(Y2, HIGH);  // Y variant B
      delay(1);
      col = analogRead(X1);
      delay(4);  
      if (abs(analogRead(X1)-col)>3) { return 0;}
      delay(3);
      if (abs(analogRead(X1)-col)>3) { return 0;}
      //if (analogRead(X1)!=col) { return 0;}
      
      //digitalWrite(Y1, LOW);  // Y variant A
      digitalWrite(Y2, LOW);  // Y variant B
      //delay(5);
      touch = !digitalRead(X1); // 0 - dotyk
      if (touch) {
        int16_t rows=ROW_L-ROW_F;
        int16_t cols=COL_L-COL_F;
        float row1=float(row-ROW_F)/rows*240;
        float col1=float(col-COL_F)/cols*320;
        T_ROW=int(row1);
        T_COL=int(col1);
        valid=1;
      }
      wait_touch=0;
    }
  }
  // Re-Set A2 A3 8 9 for ILI9341
  BD_as_output();
  DDRF = DDRF | B11110010; // A0-A4 as outputs  
  PORTF = PORTF & B11101111; // CS 0
  // To find out values for calibration F_ROW, L_ROW, F_COL, F_COL
   /* //uncomment to have the coordinates of a touch displayed
  B_COLOR=0x0C0C;
  F_SIZE=2;
  P_COL=230;
  P_ROW=200;
  Display_integer(row);
  P_COL=280;
  P_ROW=200;
  Display_integer(col);
  
  P_COL=230;
  P_ROW=220;
  Display_clear_char(3);
  Display_integer(T_ROW);
  P_COL=280;
  P_ROW=220;
  Display_clear_char(3);
  Display_integer(T_COL);
  B_COLOR=GREEN;
  F_SIZE=3;
   */
  // Draw a point where touched
//  LCD_rect(T_COL-1,T_ROW-1, 2, 2,F_COLOR);  
  T_ROW = row;
  T_COL = col;
  return valid;
}

uint16_t D_COL, D_ROW; 

void setup()
{
 // Serial.begin(115200);
  delay(200);
//  Serial.println("Start init");
  // Set pins 1-8 as output
  BD_as_output();
  
  // Set pins A0-A4 as output
  DDRC = DDRC | B00011111; 
  
  LCD_init();
  
  LCD_clear(0x0C); 
  
  B_COLOR=0x0c0c;
  F_COLOR=BLACK;
//(col,row,width,height,color),left //reference for the call parameters 
  LCD_triangle(115,75,100,100,BLUE,false); //play button
  LCD_rect(122,128,40,10, WHITE); //pause, is in the play button, so written 2nd
  LCD_rect(122,112,40,10, WHITE); //pause
  LCD_triangle(230,105,40,40,RED,false); //skip forward
  LCD_triangle(270,105,40,40,RED,false); //skip forward
  LCD_rect(310,105,5,40, RED); //skip bar
  LCD_triangle(10,105,40,40,RED,true); //skip back
  LCD_triangle(50,105,40,40,RED,true); //skip back
  LCD_rect(5,105,5,40, RED); //skip bar
  LCD_rect(200,30,40,10, YELLOW); //plus volume -
  LCD_rect(215,15,10,40, YELLOW); //plus volume |
  LCD_rect(80,30,40,10, YELLOW); //minus volume -
  LCD_rect(290,210,30,30, MAGENTA); //cursor corner lower left
  LCD_rect(0,210,30,30, MAGENTA); //cursor corner lower right
//sketch uses 6% more storage and 4% more RAM with USB functionality
  Mouse.begin();
  Keyboard.begin();
}
#define VK_MUTE         0xE2  //no 'button' for this, I just push pause
#define VK_VOL_DOWN     0xEA
#define VK_VOL_UP       0xE9
#define VK_SKIP_FORWARD 0xB5
#define VK_SKIP_BACKWARD 0xB6
#define VK_STOP         0xB7
#define VK_PLAY_PAUSE   0xCD
#define VK_MOUSE_LR     0
#define VK_MOUSE_UL     1

const int16_t y_button_centers[] = {550,550,550,250,250,840,840 };
const int16_t x_button_centers[] = {470,760,250,630,370,840,130 };
const uint8_t virtual_keys[] = { VK_PLAY_PAUSE, VK_SKIP_FORWARD, VK_SKIP_BACKWARD, VK_VOL_UP,
                                  VK_VOL_DOWN, VK_MOUSE_LR,0x1 };

void loop()
{
  byte touch=ReadTouch() ;
  if(touch) {
    uint16_t Current_error = 1000;
    uint8_t index = 0;
    for (int i=0; i<sizeof(virtual_keys); i++) {
      uint16_t error = abs((int)T_COL - x_button_centers[i]) + abs(T_ROW - y_button_centers[i]);
      if (error < Current_error){
        index = i;
        Current_error = error;
      }
    }
    if (Current_error < 99){ //if the touch is within 100 'point' (total) error of the defined points, it is a valid key press
        LCD_command_write(0x21); //on a valid keypress the screen colors are inverted, just user feedback
        switch (virtual_keys[index]){
          case VK_MOUSE_LR: //this corresponds to the lower right rectangle, it puts the mouse in the lower right corner to keep the (Mac) computer from sleeping
            for (uint8_t j = 0; j < 10; j++){
                  Mouse.move(75, 75);
                  delay(5);
            }
            break;
          case VK_MOUSE_UL: //this moves the mouse up and left, to wake the computer or take the cursor out of the corner to allow standby
             Mouse.move(-25, -25);
              break;
          default:
            Consumer.write(virtual_keys[index]);    
            break;
            
      }
        delay(100);
        LCD_command_write(0x20); //return the LCD to normal colors.
    } 
  delay(10);          

  }
}

Credits

kluger
0 projects • 1 follower

Comments