USB Media Controller
Control music playback and volume with touchscreen LCD
Components and supplies
1
Case, plastic
1
Arduino Leonardo
1
2.4 inch TFT display with touchscreen
Apps and platforms
1
Arduino IDE
Project description
Code
music_control_LCD
arduino
Controls LCD display, reads touchscreen position, and communicates over USB
1//Most of this code is from here: 2//https://gist.github.com/calogerus/79ef0c4cf04d9ea33dae9fd77a3a7316#file-ili9341_8-ino 3//The ability to draw (ASCII) characters is still in this code, but not used in my application. 4//and here: 5//https://uboopenfactory.univ-brest.fr/Les-Labs/MusicLab/Projets/Arduino-Media-Keys 6//This is for the parallel port LCD 7// Connect data pins LCD_D 0-7 to arduino Leonardo: 8// LCD_D 0 -- D8 PB4 9// LCD_D 1 -- D9 PB5 10// LCD_D 2 -- D2 PD1 11// LCD_D 3 -- D3 PD0 12// LCD_D 4 -- D4 PD4 13// LCD_D 5 -- D5 PC6 14// LCD_D 6 -- D6 PD7 15// LCD_D 7 -- D7 PE6 16// Connect command pins: 17// LCD_RST -- A4 PF1 1 -> 0 min 15 micros 0 -> 1 18// LCD_CS -- A3 PF4 chip select, aktiv LOW 19// LCD_RS -- A2 PF5 data/command select, 0 command, 1 data 20// LCD_WR -- A1 PF6 -> 1, HIGH when not used 21// LCD_RD -- A0 PF7 -> 1, HIGH when not used 22//This includes media keyboard commands and mouse outputs 23#include "HID-Project.h" 24 25#define BLACK 0x0000 26#define BLUE 0x001F 27#define RED 0xF800 28#define GREEN 0x07E0 29#define CYAN 0x07FF 30#define MAGENTA 0xF81F 31#define YELLOW 0xFFE0 32#define WHITE 0xFFFF 33 34 35// Touchscreen connection: 36// Used MCU_Friend library example 'diagnose_Touchpins' on a MEGA 2560 to discover the pins used for the touchscreen 37// (the pins are multiplexed with LCD control pins) 38// MCU_Friend does not fit on a Leonardo 39#define Y1 A3 //PF4 need two analog inputs 40#define X2 A2 //PB4 41#define Y2 9 // 42#define X1 8 // 43 44int16_t P_COL=0; // LCD cursor pointer 45int16_t P_ROW=0; 46int16_t T_COL=0; // TOUCHSCREEN(TS) detected value 47int16_t T_ROW=0; 48 49// TS calibration 50uint16_t ROW_F=157; // TS first row 51uint16_t ROW_L=880; // TS last row 52uint16_t COL_F=116; // TS first column 53uint16_t COL_L=895; // TS last column 54 55uint8_t F_SIZE=3; // font size 56uint16_t F_COLOR=WHITE; // foreground color 57uint16_t B_COLOR=0x0C0C; // background color 58 59// draw keypad 60String K_LABEL[] = {"1","2","3","4","5","6","7","8","9","0","<"}; 61uint16_t K_ROW[] = {150,150,150,100,100,100,50,50,50,200,200}; 62uint16_t K_COL[] = {10,50,90,10,50,90,10,50,90,50,90}; 63 64void LCD_write(uint8_t d) { 65 //all of the LCD interface is very specific to the Leonardo 66 // ILI9341 reads data pins when WR rises from LOW to HIGH (A1 pin on arduino) 67 PORTF = PORTF & B10111111; // WR 0 68 // data pins of ILI9341 connected to four arduino ports 69 PORTD = (PORTD & ~B10010011) | (((d) & B01000000) << 1) | // LCD_D 6 -- D6 PD7 70 ((d) & B00010000) | // LCD_D 4 -- D4 PD4 71 (((d) & B00001000) >> 3) | // LCD_D 3 -- D3 PD0 72 (((d) & B00000100) >> 1); // LCD_D 2 -- D2 PD1 73 PORTB = (PORTB & ~B00110000) | (((d) & B00000011) << 4); // LCD_D 0 -- D8 PB4 74 // LCD_D 1 -- D9 PB5 75 PORTC = (PORTC & ~B01000000) | (((d) & B00100000) << 1); // LCD_D 5 -- D5 PC6 76 PORTE = (PORTE & ~B01000000) | (((d) & B10000000) >> 1); // LCD_D 7 -- D7 PE6 77 78 PORTF = PORTF | B01000000; // WR 1 79} 80 81void LCD_command_write(uint8_t d) { 82 PORTF = PORTF & B11011111; // LCD_RS = 0, arduino pin A2 83 // write data pins 84 LCD_write(d); 85} 86 87void LCD_data_write(uint8_t d) { 88 PORTF = PORTF | B00100000; // LCD_RS = 1, arduino pin A2 89 // write data pins 90 LCD_write(d); 91} 92 93uint8_t LCD_read(void) { 94 //this doesn't work 95 // CS LOW, WR HIGH, RD HIGH->LOW>HIGH, RS(D/C) HIGH 96 PORTF = PORTF | B00100000; // LCD_RS = 1, arduino pin A2 97 98 BD_as_input(); // Set arduino pins as input 99 // LCD_RD - arduino pin A0 100 // After RD falls from HIGH to LOW ILI9341 outputs data until RD returns to HIGH 101 PORTF = PORTF & B01111111; // RD 0 102 103 uint8_t bit6432 = PIND; // Read data pins 7410 104 bit6432 = ((bit6432 & B10000000)>>1) | // LCD_D 6 -- D6 PD7 105 (bit6432 & B00010000) | // LCD_D 4 -- D4 PD4 106 ((bit6432 & B00000010)<<1) | // LCD_D 2 -- D2 PD1 107 ((bit6432 & B00000001)<<3); // LCD_D 3 -- D3 PD0 108 uint8_t bit10 = (PINB & B00110000) >> 4;// LCD_D 0 -- D8 PB4 109 // LCD_D 1 -- D9 PB5 110 uint8_t bit5 = (PINC & B01000000) >> 1; // LCD_D 5 -- D5 PC6 111 uint8_t bit7 = (PINE & B01000000) << 1; // LCD_D 7 -- D7 PE6 112 113 PORTF = PORTF | B10000000; // RD 1 114 BD_as_output(); // Re-Set arduino pins as output 115 return (bit6432 | bit10 | bit5 | bit7); 116} 117 118void BD_as_input(void) { 119 // 120 DDRD = DDRD & ~B10010011; 121 DDRB = DDRB & ~B00110000; 122 DDRC = DDRC & ~B01000000; 123 DDRE = DDRC & ~B01000000; 124} 125 126void BD_as_output(void) { 127 DDRD = DDRD | B10010011; 128 DDRB = DDRB | B00110000; 129 DDRC = DDRC | B01000000; 130 DDRE = DDRC | B01000000; 131} 132 133void LCD_init(void) { 134 // LCD_RESET 1 - 0 - 1, arduino pin A4 135 DDRF = DDRF | 11110010; 136 PORTF = PORTF | B11110010; // 1 137 delay(10); 138 PORTF = PORTF & B11111101; // 0 139 delay(20); 140 PORTF = PORTF | B00000010; // 1 141 delay(20); 142 143 // CS HIGH, WR HIGH, RD HIGH, CS LOW 144 PORTF = PORTF | B11110010; // CS 1 WR 1 RD 1 145 delay(1); 146 PORTF = PORTF & B11101111; // CS 0 147 148 LCD_command_write(0xF7); // Pump ratio control 149 LCD_data_write(0x20); // 150 151 LCD_command_write(0x3A); // COLMOD: Pixel Format Set 152 LCD_data_write(0x55); 153 154 LCD_command_write(0x36); // Memory Access Control 155 // MY - Row Address Order (bit7) 156 // MX - Column Address Order 157 // MV - Row / Column Exchange 158 // ML - Vertical Refresh Order 159 // BGR - RGB-BGR Order 160 // MH - Horizontal Refresh ORDER(bit2) 161 LCD_data_write(B00001000); 162 163 LCD_command_write(0x11); // Sleep OUT 164 LCD_command_write(0x29); // Display ON 165 166 delay(50); 167 LCD_command_write(0xD3); // Read ID, doesn't work 168 LCD_read(); 169 LCD_read(); 170 LCD_read(); 171 LCD_read(); 172} 173 174void LCD_rect(int16_t col,int16_t row, int16_t width, int16_t height, int16_t color) { 175 176 LCD_command_write(0x2a); // Column Address Set 177 LCD_data_write(row>>8); 178 LCD_data_write(row); 179 LCD_data_write((row+height-1)>>8); 180 LCD_data_write(row+height-1); 181 LCD_command_write(0x2b); // Page Address Set 182 LCD_data_write(col>>8); 183 LCD_data_write(col); 184 LCD_data_write((col+width-1)>>8); 185 LCD_data_write(col+width-1); 186 LCD_command_write(0x2c); // Memory Write 187 188 byte chigh=color >> 8; 189 byte clow=color; 190 int i,j; 191 for(i=0;i<width;i++) 192 for(j=0;j<height;j++) 193 { 194 LCD_data_write(chigh); 195 LCD_data_write(clow); 196 } 197} 198/* 199 * This routine draws equalateral triangles 'pointed' left or right 200 * it uses the y = mx + b line formula to determine if points are inside the two lines 201 * the slope m is alway 0.5 202 */ 203void LCD_triangle(int16_t col,int16_t row, int16_t width, int16_t height, int16_t color, bool left) { 204 bool inside = false; 205 LCD_command_write(0x2a); // Column Address Set 206 LCD_data_write(row>>8); 207 LCD_data_write(row); 208 LCD_data_write((row+height-1)>>8); 209 LCD_data_write(row+height-1); 210 LCD_command_write(0x2b); // Page Address Set 211 LCD_data_write(col>>8); 212 LCD_data_write(col); 213 LCD_data_write((col+width-1)>>8); 214 LCD_data_write(col+width-1); 215 LCD_command_write(0x2c); // Memory Write 216 byte bhigh = B_COLOR >> 8; 217 byte blow = B_COLOR; 218 byte chigh=color >> 8; 219 byte clow=color; 220 int i,j; 221 for(i=0;i<width;i++) 222 for(j=0;j<height;j++) 223 { 224 if (left) { 225 inside = (j <= ((i * 0.5) + (height / 2.0))) && (j >= ((height / 2.0) - (i * .5))); 226 } else inside = (j >= (i * 0.5)) && (j <= (height - (i * .5))); 227 if (inside){ 228 LCD_data_write(chigh); 229 LCD_data_write(clow); 230 }else { 231 LCD_data_write(bhigh); 232 LCD_data_write(blow); 233 } 234 } 235} 236 237void LCD_clear(byte color) { 238 /* 239 Accelerate screen clearing sacrifing color depth. Instead of writing 240 to data bits high and low byte of the color for each pixel, which takes more 241 than 300ms to fill the screen, set once data bits to 0's for black or 242 to 1's for white and start changing control bit WR from LOW to HIGH to 243 write whole area. It takes cca 70 ms. In this way the color of screen are 244 limited to those with the same high and low byte. For example setting color 245 to 0x0C fills the screen with color 0x0C0C. 246 Writing two pixels in one cycle lowering cycle count from 76800 (240x320) to 247 38400 clears screen in less then 30ms. 248 */ 249 250 LCD_command_write(0x2a); 251 LCD_data_write(0); 252 LCD_data_write(0); 253 LCD_data_write(0); 254 LCD_data_write(0xEC); 255 LCD_command_write(0x2b); 256 LCD_data_write(0); 257 LCD_data_write(0); 258 LCD_data_write(1); 259 LCD_data_write(0x3F); 260 LCD_command_write(0x2c); 261 262 PORTF = PORTF | B00100000; // LCD_RS = 1, arduino pin A2 263 264 PORTD = (PORTD & ~B10010011) | (((color) & B01000000) << 1) | 265 ((color) & B00010000) | 266 (((color) & B00001000) >> 3) | 267 (((color) & B00000100) >> 1); 268 PORTB = (PORTB & ~B00110000) | (((color) & B00000011) << 4); 269 PORTC = (PORTC & ~B01000000) | (((color) & B00100000) << 1); 270 PORTE = (PORTE & ~B01000000) | (((color) & B10000000) >> 1); 271 272 uint16_t x; 273 x=38400; // 240*320/2PORTF = ; // WR 0 274 byte wr0= PORTF & B10111111; // set WR 0 275 byte wr1= PORTF | B01000000; // set WR 1 276 for(uint16_t y=0;y<x;y++) 277 { 278 PORTF = wr0; 279 PORTF = wr1; 280 PORTF = wr0; 281 PORTF = wr1; 282 283 PORTF = wr0; 284 PORTF = wr1; 285 PORTF = wr0; 286 PORTF = wr1; 287 } 288} 289 290void Display_integer(int16_t n) { 291 String str=String(n); 292 byte l=str.length(); 293 char b[l+1]; // +1 for the null terminator 294 str.toCharArray(b,l+1); 295 for(int n=0; n<l; n++) { 296 Display_char(b[n]); 297 } 298} 299 300void Display_string(String str) { 301 byte l=str.length(); 302 char b[l+1]; // +1 for the null terminator 303 str.toCharArray(b,l+1); 304 for(int n=0; n<l; n++) { 305 Display_char(b[n]); 306 } 307} 308 309void Display_char(char znak) { 310 static const byte ASCII[][5] = 311 { 312 {0x00, 0x00, 0x00, 0x00, 0x00}, // 20 313 {0x00, 0x00, 0x5f, 0x00, 0x00}, // 21 ! 314 {0x00, 0x07, 0x00, 0x07, 0x00}, // 22 " 315 {0x14, 0x7f, 0x14, 0x7f, 0x14}, // 23 # 316 {0x24, 0x2a, 0x7f, 0x2a, 0x12} ,// 24 $ 317 {0x23, 0x13, 0x08, 0x64, 0x62}, // 25 % 318 {0x36, 0x49, 0x55, 0x22, 0x50}, // 26 & 319 {0x00, 0x00, 0x07, 0x05, 0x07}, // 27 ' 320 {0x00, 0x1c, 0x22, 0x41, 0x00}, // 28 ( 321 {0x00, 0x41, 0x22, 0x1c, 0x00}, // 29 ) 322 {0x14, 0x08, 0x3e, 0x08, 0x14}, // 2a * 323 {0x08, 0x08, 0x3e, 0x08, 0x08}, // 2b + 324 {0x00, 0x50, 0x30, 0x00, 0x00}, // 2c , 325 {0x08, 0x08, 0x08, 0x08, 0x08}, // 2d - 326 {0x00, 0x60, 0x60, 0x00, 0x00}, // 2e . 327 {0x20, 0x10, 0x08, 0x04, 0x02}, // 2f / 328 {0x3e, 0x51, 0x49, 0x45, 0x3e}, // 30 0 329 {0x00, 0x42, 0x7f, 0x40, 0x00}, // 31 1 330 {0x42, 0x61, 0x51, 0x49, 0x46}, // 32 2 331 {0x21, 0x41, 0x45, 0x4b, 0x31}, // 33 3 332 {0x18, 0x14, 0x12, 0x7f, 0x10}, // 34 4 333 {0x27, 0x45, 0x45, 0x45, 0x39}, // 35 5 334 {0x3c, 0x4a, 0x49, 0x49, 0x30}, // 36 6 335 {0x01, 0x71, 0x09, 0x05, 0x03}, // 37 7 336 {0x36, 0x49, 0x49, 0x49, 0x36}, // 38 8 337 {0x06, 0x49, 0x49, 0x29, 0x1e}, // 39 9 338 {0x00, 0x36, 0x36, 0x00, 0x00}, // 3a : 339 {0x00, 0x56, 0x36, 0x00, 0x00}, // 3b ; 340 {0x08, 0x14, 0x22, 0x41, 0x00}, // 3c < 341 {0x14, 0x14, 0x14, 0x14, 0x14}, // 3d = 342 {0x00, 0x41, 0x22, 0x14, 0x08}, // 3e > 343 {0x02, 0x01, 0x51, 0x09, 0x06}, // 3f ? 344 {0x32, 0x49, 0x79, 0x41, 0x3e}, // 40 @ 345 {0x7e, 0x11, 0x11, 0x11, 0x7e}, // 41 A 346 {0x7f, 0x49, 0x49, 0x49, 0x36}, // 42 B 347 {0x3e, 0x41, 0x41, 0x41, 0x22}, // 43 C 348 {0x7f, 0x41, 0x41, 0x22, 0x1c}, // 44 D 349 {0x7f, 0x49, 0x49, 0x49, 0x41}, // 45 E 350 {0x7f, 0x09, 0x09, 0x09, 0x01}, // 46 F 351 {0x3e, 0x41, 0x49, 0x49, 0x7a}, // 47 G 352 {0x7f, 0x08, 0x08, 0x08, 0x7f}, // 48 H 353 {0x00, 0x41, 0x7f, 0x41, 0x00}, // 49 I 354 {0x20, 0x40, 0x41, 0x3f, 0x01}, // 4a J 355 {0x7f, 0x08, 0x14, 0x22, 0x41}, // 4b K 356 {0x7f, 0x40, 0x40, 0x40, 0x40}, // 4c L 357 {0x7f, 0x02, 0x0c, 0x02, 0x7f}, // 4d M 358 {0x7f, 0x04, 0x08, 0x10, 0x7f}, // 4e N 359 {0x3e, 0x41, 0x41, 0x41, 0x3e}, // 4f O 360 {0x7f, 0x09, 0x09, 0x09, 0x06}, // 50 P 361 {0x3e, 0x41, 0x51, 0x21, 0x5e}, // 51 Q 362 {0x7f, 0x09, 0x19, 0x29, 0x46}, // 52 R 363 {0x46, 0x49, 0x49, 0x49, 0x31}, // 53 S 364 {0x01, 0x01, 0x7f, 0x01, 0x01}, // 54 T 365 {0x3f, 0x40, 0x40, 0x40, 0x3f}, // 55 U 366 {0x1f, 0x20, 0x40, 0x20, 0x1f}, // 56 V 367 {0x3f, 0x40, 0x38, 0x40, 0x3f}, // 57 W 368 {0x63, 0x14, 0x08, 0x14, 0x63}, // 58 X 369 {0x07, 0x08, 0x70, 0x08, 0x07}, // 59 Y 370 {0x61, 0x51, 0x49, 0x45, 0x43}, // 5a Z 371 {0x00, 0x7f, 0x41, 0x41, 0x00}, // 5b [ 372 {0x02, 0x04, 0x08, 0x10, 0x20}, // 5c Y 373 {0x00, 0x41, 0x41, 0x7f, 0x00}, // 5d ] 374 {0x04, 0x02, 0x01, 0x02, 0x04}, // 5e ^ 375 {0x40, 0x40, 0x40, 0x40, 0x40}, // 5f _ 376 {0x00, 0x01, 0x02, 0x04, 0x00}, // 60 ` 377 {0x20, 0x54, 0x54, 0x54, 0x78}, // 61 a 378 {0x7f, 0x48, 0x44, 0x44, 0x38}, // 62 b 379 {0x38, 0x44, 0x44, 0x44, 0x20}, // 63 c 380 {0x38, 0x44, 0x44, 0x48, 0x7f}, // 64 d 381 {0x38, 0x54, 0x54, 0x54, 0x18}, // 65 e 382 {0x08, 0x7e, 0x09, 0x01, 0x02}, // 66 f 383 {0x0c, 0x52, 0x52, 0x52, 0x3e}, // 67 g 384 {0x7f, 0x08, 0x04, 0x04, 0x78}, // 68 h 385 {0x00, 0x44, 0x7d, 0x40, 0x00}, // 69 i 386 {0x20, 0x40, 0x44, 0x3d, 0x00}, // 6a j 387 {0x7f, 0x10, 0x28, 0x44, 0x00}, // 6b k 388 {0x00, 0x41, 0x7f, 0x40, 0x00}, // 6c l 389 {0x7c, 0x04, 0x18, 0x04, 0x78}, // 6d m 390 {0x7c, 0x08, 0x04, 0x04, 0x78}, // 6e n 391 {0x38, 0x44, 0x44, 0x44, 0x38}, // 6f o 392 {0x7c, 0x14, 0x14, 0x14, 0x08}, // 70 p 393 {0x08, 0x14, 0x14, 0x18, 0x7c}, // 71 q 394 {0x7c, 0x08, 0x04, 0x04, 0x08}, // 72 r 395 {0x48, 0x54, 0x54, 0x54, 0x20}, // 73 s 396 {0x04, 0x3f, 0x44, 0x40, 0x20}, // 74 t 397 {0x3c, 0x40, 0x40, 0x20, 0x7c}, // 75 u 398 {0x1c, 0x20, 0x40, 0x20, 0x1c}, // 76 v 399 {0x3c, 0x40, 0x30, 0x40, 0x3c}, // 77 w 400 {0x44, 0x28, 0x10, 0x28, 0x44}, // 78 x 401 {0x0c, 0x50, 0x50, 0x50, 0x3c}, // 79 y 402 {0x44, 0x64, 0x54, 0x4c, 0x44}, // 7a z 403 {0x00, 0x08, 0x36, 0x41, 0x00}, // 7b { 404 {0x00, 0x00, 0x7f, 0x00, 0x00}, // 7c | 405 {0x00, 0x41, 0x36, 0x08, 0x00}, // 7d } 406 {0x10, 0x08, 0x08, 0x10, 0x08}, // 7e 407 {0x00, 0x06, 0x09, 0x09, 0x06} // 7f 408 }; 409 410 int8_t size=F_SIZE; 411 int16_t color=F_COLOR; 412 int16_t bcolor=B_COLOR; 413 414 if( (P_COL+(size*6)) > 319) { 415 P_COL=0; 416 P_ROW+=size*(8+1); 417 } 418 419 LCD_command_write(0x2a); // ROWS 420 LCD_data_write(P_ROW>>8); 421 LCD_data_write(P_ROW); 422 LCD_data_write(((P_ROW+size*8)-1)>>8); 423 LCD_data_write((P_ROW+size*8)-1); 424 LCD_command_write(0x2b); // COLUMNS 425 LCD_data_write(P_COL>>8); 426 LCD_data_write(P_COL); 427 LCD_data_write((P_COL+(size*6))>>8); 428 LCD_data_write(P_COL+(size*6)); 429 LCD_command_write(0x2c); 430 byte bchigh=bcolor >> 8; 431 byte bclow=bcolor; 432 byte fchigh=color >> 8; 433 byte fclow=color; 434 byte index, nbit, i, j; 435 for (index = 0; index < 5; index++) { 436 char col=ASCII[znak - 0x20][index]; 437 for ( i=0; i<size; i++){ 438 byte mask=B00000001; 439 for (nbit = 0; nbit < 8; nbit++) { 440 if (col & mask) { 441 for (j=0; j<size; j++){ 442 LCD_data_write(fchigh); 443 LCD_data_write(fclow); 444 } 445 } 446 else { 447 for (j=0; j<size; j++){ 448 LCD_data_write(bchigh); 449 LCD_data_write(bclow); 450 } 451 } 452 mask=mask<<1; 453 } 454 } 455 } 456 P_COL+=size*6; 457} 458 459void Display_clear_char(byte n) { 460 // delete n chars 461 int8_t size=F_SIZE; 462 int16_t bcolor=B_COLOR; 463 464 LCD_command_write(0x2a); // ROWS 465 LCD_data_write(P_ROW>>8); 466 LCD_data_write(P_ROW); 467 LCD_data_write(((P_ROW+size*8)-1)>>8); 468 LCD_data_write((P_ROW+size*8)-1); 469 LCD_command_write(0x2b); // COLUMNS 470 LCD_data_write(P_COL>>8); 471 LCD_data_write(P_COL); 472 LCD_data_write((P_COL+(size*6*n))>>8); 473 LCD_data_write(P_COL+(size*6*n)); 474 LCD_command_write(0x2c); 475 476 byte bchigh=bcolor >> 8; 477 byte bclow=bcolor; 478 int16_t cyc=size*8 * size*6*n; 479 for (int16_t i=0; i<cyc; i++) { 480 LCD_data_write(bchigh); 481 LCD_data_write(bclow); 482 } 483} 484 485byte ReadTouch(void) { 486 //Y1 A3 A2 487 //X1 A2 A1 488 //Y2 9 6 489 //X2 8 7 490 int16_t row, col; 491 int8_t touch, wait_touch, valid; 492 wait_touch=1; 493 valid=0; 494 PORTF = PORTF | B00010000; // CS 1 495 while (wait_touch) { 496 pinMode(Y1, INPUT); 497 pinMode(Y2, INPUT_PULLUP); 498 499 pinMode(X1, OUTPUT); 500 pinMode(X2, OUTPUT); 501 digitalWrite(X1, LOW); 502 digitalWrite(X2, LOW); 503 504 touch = !digitalRead(Y1); // 0 - touched 505 if (touch) { 506 //delay(5); 507 digitalWrite(X1, HIGH); // X variant A 508 //digitalWrite(X2, HIGH); // X variant B 509 delay(1); 510 row = analogRead(Y1); 511 delay(4); 512 if (abs(analogRead(Y1)-row)>3) { return 0;} 513 delay(3); 514 if (abs(analogRead(Y1)-row)>3) { return 0;} 515 //if (analogRead(Y1)!=row) { return 0;} 516 517 pinMode(X1, INPUT); 518 pinMode(X2, INPUT_PULLUP); 519 520 pinMode(Y1, OUTPUT); 521 pinMode(Y2, OUTPUT); 522 //digitalWrite(Y1, HIGH); // Y variant A 523 //digitalWrite(Y2, LOW); // Y variant A 524 digitalWrite(Y1, LOW); // Y variant B 525 digitalWrite(Y2, HIGH); // Y variant B 526 delay(1); 527 col = analogRead(X1); 528 delay(4); 529 if (abs(analogRead(X1)-col)>3) { return 0;} 530 delay(3); 531 if (abs(analogRead(X1)-col)>3) { return 0;} 532 //if (analogRead(X1)!=col) { return 0;} 533 534 //digitalWrite(Y1, LOW); // Y variant A 535 digitalWrite(Y2, LOW); // Y variant B 536 //delay(5); 537 touch = !digitalRead(X1); // 0 - dotyk 538 if (touch) { 539 int16_t rows=ROW_L-ROW_F; 540 int16_t cols=COL_L-COL_F; 541 float row1=float(row-ROW_F)/rows*240; 542 float col1=float(col-COL_F)/cols*320; 543 T_ROW=int(row1); 544 T_COL=int(col1); 545 valid=1; 546 } 547 wait_touch=0; 548 } 549 } 550 // Re-Set A2 A3 8 9 for ILI9341 551 BD_as_output(); 552 DDRF = DDRF | B11110010; // A0-A4 as outputs 553 PORTF = PORTF & B11101111; // CS 0 554 // To find out values for calibration F_ROW, L_ROW, F_COL, F_COL 555 /* //uncomment to have the coordinates of a touch displayed 556 B_COLOR=0x0C0C; 557 F_SIZE=2; 558 P_COL=230; 559 P_ROW=200; 560 Display_integer(row); 561 P_COL=280; 562 P_ROW=200; 563 Display_integer(col); 564 565 P_COL=230; 566 P_ROW=220; 567 Display_clear_char(3); 568 Display_integer(T_ROW); 569 P_COL=280; 570 P_ROW=220; 571 Display_clear_char(3); 572 Display_integer(T_COL); 573 B_COLOR=GREEN; 574 F_SIZE=3; 575 */ 576 // Draw a point where touched 577// LCD_rect(T_COL-1,T_ROW-1, 2, 2,F_COLOR); 578 T_ROW = row; 579 T_COL = col; 580 return valid; 581} 582 583uint16_t D_COL, D_ROW; 584 585void setup() 586{ 587 // Serial.begin(115200); 588 delay(200); 589// Serial.println("Start init"); 590 // Set pins 1-8 as output 591 BD_as_output(); 592 593 // Set pins A0-A4 as output 594 DDRC = DDRC | B00011111; 595 596 LCD_init(); 597 598 LCD_clear(0x0C); 599 600 B_COLOR=0x0c0c; 601 F_COLOR=BLACK; 602//(col,row,width,height,color),left //reference for the call parameters 603 LCD_triangle(115,75,100,100,BLUE,false); //play button 604 LCD_rect(122,128,40,10, WHITE); //pause, is in the play button, so written 2nd 605 LCD_rect(122,112,40,10, WHITE); //pause 606 LCD_triangle(230,105,40,40,RED,false); //skip forward 607 LCD_triangle(270,105,40,40,RED,false); //skip forward 608 LCD_rect(310,105,5,40, RED); //skip bar 609 LCD_triangle(10,105,40,40,RED,true); //skip back 610 LCD_triangle(50,105,40,40,RED,true); //skip back 611 LCD_rect(5,105,5,40, RED); //skip bar 612 LCD_rect(200,30,40,10, YELLOW); //plus volume - 613 LCD_rect(215,15,10,40, YELLOW); //plus volume | 614 LCD_rect(80,30,40,10, YELLOW); //minus volume - 615 LCD_rect(290,210,30,30, MAGENTA); //cursor corner lower left 616 LCD_rect(0,210,30,30, MAGENTA); //cursor corner lower right 617//sketch uses 6% more storage and 4% more RAM with USB functionality 618 Mouse.begin(); 619 Keyboard.begin(); 620} 621#define VK_MUTE 0xE2 //no 'button' for this, I just push pause 622#define VK_VOL_DOWN 0xEA 623#define VK_VOL_UP 0xE9 624#define VK_SKIP_FORWARD 0xB5 625#define VK_SKIP_BACKWARD 0xB6 626#define VK_STOP 0xB7 627#define VK_PLAY_PAUSE 0xCD 628#define VK_MOUSE_LR 0 629#define VK_MOUSE_UL 1 630 631const int16_t y_button_centers[] = {550,550,550,250,250,840,840 }; 632const int16_t x_button_centers[] = {470,760,250,630,370,840,130 }; 633const uint8_t virtual_keys[] = { VK_PLAY_PAUSE, VK_SKIP_FORWARD, VK_SKIP_BACKWARD, VK_VOL_UP, 634 VK_VOL_DOWN, VK_MOUSE_LR,0x1 }; 635 636void loop() 637{ 638 byte touch=ReadTouch() ; 639 if(touch) { 640 uint16_t Current_error = 1000; 641 uint8_t index = 0; 642 for (int i=0; i<sizeof(virtual_keys); i++) { 643 uint16_t error = abs((int)T_COL - x_button_centers[i]) + abs(T_ROW - y_button_centers[i]); 644 if (error < Current_error){ 645 index = i; 646 Current_error = error; 647 } 648 } 649 if (Current_error < 99){ //if the touch is within 100 'point' (total) error of the defined points, it is a valid key press 650 LCD_command_write(0x21); //on a valid keypress the screen colors are inverted, just user feedback 651 switch (virtual_keys[index]){ 652 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 653 for (uint8_t j = 0; j < 10; j++){ 654 Mouse.move(75, 75); 655 delay(5); 656 } 657 break; 658 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 659 Mouse.move(-25, -25); 660 break; 661 default: 662 Consumer.write(virtual_keys[index]); 663 break; 664 665 } 666 delay(100); 667 LCD_command_write(0x20); //return the LCD to normal colors. 668 } 669 delay(10); 670 671 } 672} 673
music_control_LCD
arduino
Controls LCD display, reads touchscreen position, and communicates over USB
1//Most of this code is from here: 2//https://gist.github.com/calogerus/79ef0c4cf04d9ea33dae9fd77a3a7316#file-ili9341_8-ino 3//The 4 ability to draw (ASCII) characters is still in this code, but not used in my application. 5//and 6 here: 7//https://uboopenfactory.univ-brest.fr/Les-Labs/MusicLab/Projets/Arduino-Media-Keys 8//This 9 is for the parallel port LCD 10// Connect data pins LCD_D 0-7 to arduino Leonardo: 11// 12 LCD_D 0 -- D8 PB4 13// LCD_D 1 -- D9 PB5 14// LCD_D 2 -- D2 PD1 15// LCD_D 3 16 -- D3 PD0 17// LCD_D 4 -- D4 PD4 18// LCD_D 5 -- D5 PC6 19// LCD_D 6 -- D6 PD7 20// 21 LCD_D 7 -- D7 PE6 22// Connect command pins: 23// LCD_RST -- A4 PF1 1 -> 0 min 24 15 micros 0 -> 1 25// LCD_CS -- A3 PF4 chip select, aktiv LOW 26// LCD_RS 27 -- A2 PF5 data/command select, 0 command, 1 data 28// LCD_WR -- A1 PF6 -> 29 1, HIGH when not used 30// LCD_RD -- A0 PF7 -> 1, HIGH when not used 31//This 32 includes media keyboard commands and mouse outputs 33#include "HID-Project.h" 34 35#define 36 BLACK 0x0000 37#define BLUE 0x001F 38#define RED 0xF800 39#define GREEN 40 0x07E0 41#define CYAN 0x07FF 42#define MAGENTA 0xF81F 43#define YELLOW 44 0xFFE0 45#define WHITE 0xFFFF 46 47 48// Touchscreen connection: 49// Used 50 MCU_Friend library example 'diagnose_Touchpins' on a MEGA 2560 to discover the pins 51 used for the touchscreen 52// (the pins are multiplexed with LCD control pins) 53// 54 MCU_Friend does not fit on a Leonardo 55#define Y1 A3 //PF4 need two analog inputs 56#define 57 X2 A2 //PB4 58#define Y2 9 // 59#define X1 8 // 60 61int16_t P_COL=0; 62 // LCD cursor pointer 63int16_t P_ROW=0; 64int16_t T_COL=0; // TOUCHSCREEN(TS) 65 detected value 66int16_t T_ROW=0; 67 68// TS calibration 69uint16_t ROW_F=157; 70 // TS first row 71uint16_t ROW_L=880; // TS last row 72uint16_t COL_F=116; // 73 TS first column 74uint16_t COL_L=895; // TS last column 75 76uint8_t F_SIZE=3; 77 // font size 78uint16_t F_COLOR=WHITE; // foreground color 79uint16_t B_COLOR=0x0C0C; 80 // background color 81 82// draw keypad 83String K_LABEL[] = {"1","2","3","4","5","6","7","8","9","0","<"}; 84uint16_t 85 K_ROW[] = {150,150,150,100,100,100,50,50,50,200,200}; 86uint16_t K_COL[] = {10,50,90,10,50,90,10,50,90,50,90}; 87 88void 89 LCD_write(uint8_t d) { 90 //all of the LCD interface is very specific to the Leonardo 91 92 // ILI9341 reads data pins when WR rises from LOW to HIGH (A1 pin on arduino) 93 94 PORTF = PORTF & B10111111; // WR 0 95 // data pins of ILI9341 connected to four 96 arduino ports 97 PORTD = (PORTD & ~B10010011) | (((d) & B01000000) << 1) | // 98 LCD_D 6 -- D6 PD7 99 ((d) & B00010000) | // 100 LCD_D 4 -- D4 PD4 101 (((d) & B00001000) >> 3) | 102 // LCD_D 3 -- D3 PD0 103 (((d) & B00000100) >> 1); 104 // LCD_D 2 -- D2 PD1 105 PORTB = (PORTB & ~B00110000) | (((d) & B00000011) << 106 4); // LCD_D 0 -- D8 PB4 107 // 108 LCD_D 1 -- D9 PB5 109 PORTC = (PORTC & ~B01000000) | (((d) & B00100000) << 1); 110 // LCD_D 5 -- D5 PC6 111 PORTE = (PORTE & ~B01000000) | (((d) & B10000000) >> 112 1); // LCD_D 7 -- D7 PE6 113 114 PORTF = PORTF | B01000000; // WR 1 115} 116 117void 118 LCD_command_write(uint8_t d) { 119 PORTF = PORTF & B11011111; // LCD_RS = 0, arduino 120 pin A2 121 // write data pins 122 LCD_write(d); 123} 124 125void LCD_data_write(uint8_t 126 d) { 127 PORTF = PORTF | B00100000; // LCD_RS = 1, arduino pin A2 128 // write 129 data pins 130 LCD_write(d); 131} 132 133uint8_t LCD_read(void) { 134 //this doesn't 135 work 136 // CS LOW, WR HIGH, RD HIGH->LOW>HIGH, RS(D/C) HIGH 137 PORTF = PORTF 138 | B00100000; // LCD_RS = 1, arduino pin A2 139 140 BD_as_input(); // Set arduino 141 pins as input 142 // LCD_RD - arduino pin A0 143 // After RD falls from HIGH to 144 LOW ILI9341 outputs data until RD returns to HIGH 145 PORTF = PORTF & B01111111; 146 // RD 0 147 148 uint8_t bit6432 = PIND; // Read data pins 7410 149 bit6432 = 150 ((bit6432 & B10000000)>>1) | // LCD_D 6 -- D6 PD7 151 (bit6432 & B00010000) 152 | // LCD_D 4 -- D4 PD4 153 ((bit6432 & B00000010)<<1) | // LCD_D 154 2 -- D2 PD1 155 ((bit6432 & B00000001)<<3); // LCD_D 3 -- D3 PD0 156 157 uint8_t bit10 = (PINB & B00110000) >> 4;// LCD_D 0 -- D8 PB4 158 // 159 LCD_D 1 -- D9 PB5 160 uint8_t bit5 = (PINC & B01000000) >> 1; // LCD_D 5 -- D5 161 PC6 162 uint8_t bit7 = (PINE & B01000000) << 1; // LCD_D 7 -- D7 PE6 163 164 PORTF 165 = PORTF | B10000000; // RD 1 166 BD_as_output(); // Re-Set arduino pins as output 167 168 return (bit6432 | bit10 | bit5 | bit7); 169} 170 171void BD_as_input(void) { 172 173 // 174 DDRD = DDRD & ~B10010011; 175 DDRB = DDRB & ~B00110000; 176 DDRC 177 = DDRC & ~B01000000; 178 DDRE = DDRC & ~B01000000; 179} 180 181void BD_as_output(void) 182 { 183 DDRD = DDRD | B10010011; 184 DDRB = DDRB | B00110000; 185 DDRC = DDRC 186 | B01000000; 187 DDRE = DDRC | B01000000; 188} 189 190void LCD_init(void) { 191 192 // LCD_RESET 1 - 0 - 1, arduino pin A4 193 DDRF = DDRF | 11110010; 194 PORTF 195 = PORTF | B11110010; // 1 196 delay(10); 197 PORTF = PORTF & B11111101; // 0 198 199 delay(20); 200 PORTF = PORTF | B00000010; // 1 201 delay(20); 202 203 // 204 CS HIGH, WR HIGH, RD HIGH, CS LOW 205 PORTF = PORTF | B11110010; // CS 1 WR 1 RD 206 1 207 delay(1); 208 PORTF = PORTF & B11101111; // CS 0 209 210 LCD_command_write(0xF7); 211 // Pump ratio control 212 LCD_data_write(0x20); // 213 214 LCD_command_write(0x3A); 215 // COLMOD: Pixel Format Set 216 LCD_data_write(0x55); 217 218 LCD_command_write(0x36); 219 // Memory Access Control 220 // MY - Row Address Order (bit7) 221 // MX - Column 222 Address Order 223 // MV - Row / Column Exchange 224 // ML - Vertical Refresh 225 Order 226 // BGR - RGB-BGR Order 227 // MH - Horizontal Refresh ORDER(bit2) 228 229 LCD_data_write(B00001000); 230 231 LCD_command_write(0x11); // Sleep OUT 232 233 LCD_command_write(0x29); // Display ON 234 235 delay(50); 236 LCD_command_write(0xD3); 237 // Read ID, doesn't work 238 LCD_read(); 239 LCD_read(); 240 LCD_read(); 241 242 LCD_read(); 243} 244 245void LCD_rect(int16_t col,int16_t row, int16_t width, 246 int16_t height, int16_t color) { 247 248 LCD_command_write(0x2a); // Column Address 249 Set 250 LCD_data_write(row>>8); 251 LCD_data_write(row); 252 LCD_data_write((row+height-1)>>8); 253 254 LCD_data_write(row+height-1); 255 LCD_command_write(0x2b); // Page Address Set 256 257 LCD_data_write(col>>8); 258 LCD_data_write(col); 259 LCD_data_write((col+width-1)>>8); 260 261 LCD_data_write(col+width-1); 262 LCD_command_write(0x2c); // Memory Write 263 264 265 byte chigh=color >> 8; 266 byte clow=color; 267 int i,j; 268 for(i=0;i<width;i++) 269 270 for(j=0;j<height;j++) 271 { 272 LCD_data_write(chigh); 273 LCD_data_write(clow); 274 275 } 276} 277/* 278 * This routine draws equalateral triangles 'pointed' left or 279 right 280 * it uses the y = mx + b line formula to determine if points are inside 281 the two lines 282 * the slope m is alway 0.5 283 */ 284void LCD_triangle(int16_t 285 col,int16_t row, int16_t width, int16_t height, int16_t color, bool left) { 286 287 bool inside = false; 288 LCD_command_write(0x2a); // Column Address Set 289 LCD_data_write(row>>8); 290 291 LCD_data_write(row); 292 LCD_data_write((row+height-1)>>8); 293 LCD_data_write(row+height-1); 294 295 LCD_command_write(0x2b); // Page Address Set 296 LCD_data_write(col>>8); 297 298 LCD_data_write(col); 299 LCD_data_write((col+width-1)>>8); 300 LCD_data_write(col+width-1); 301 302 LCD_command_write(0x2c); // Memory Write 303 byte bhigh = B_COLOR >> 8; 304 byte 305 blow = B_COLOR; 306 byte chigh=color >> 8; 307 byte clow=color; 308 int i,j; 309 310 for(i=0;i<width;i++) 311 for(j=0;j<height;j++) 312 { 313 if (left) 314 { 315 inside = (j <= ((i * 0.5) + (height / 2.0))) && (j >= ((height / 2.0) 316 - (i * .5))); 317 } else inside = (j >= (i * 0.5)) && (j <= (height - (i * 318 .5))); 319 if (inside){ 320 LCD_data_write(chigh); 321 LCD_data_write(clow); 322 323 }else { 324 LCD_data_write(bhigh); 325 LCD_data_write(blow); 326 327 } 328 } 329} 330 331void LCD_clear(byte color) { 332 /* 333 Accelerate 334 screen clearing sacrifing color depth. Instead of writing 335 to data bits high 336 and low byte of the color for each pixel, which takes more 337 than 300ms to fill 338 the screen, set once data bits to 0's for black or 339 to 1's for white and start 340 changing control bit WR from LOW to HIGH to 341 write whole area. It takes cca 342 70 ms. In this way the color of screen are 343 limited to those with the same high 344 and low byte. For example setting color 345 to 0x0C fills the screen with color 346 0x0C0C. 347 Writing two pixels in one cycle lowering cycle count from 76800 (240x320) 348 to 349 38400 clears screen in less then 30ms. 350 */ 351 352 LCD_command_write(0x2a); 353 354 LCD_data_write(0); 355 LCD_data_write(0); 356 LCD_data_write(0); 357 LCD_data_write(0xEC); 358 359 LCD_command_write(0x2b); 360 LCD_data_write(0); 361 LCD_data_write(0); 362 363 LCD_data_write(1); 364 LCD_data_write(0x3F); 365 LCD_command_write(0x2c); 366 367 368 PORTF = PORTF | B00100000; // LCD_RS = 1, arduino pin A2 369 370 PORTD 371 = (PORTD & ~B10010011) | (((color) & B01000000) << 1) | 372 ((color) 373 & B00010000) | 374 (((color) & B00001000) >> 3) 375 | 376 (((color) & B00000100) >> 1); 377 PORTB 378 = (PORTB & ~B00110000) | (((color) & B00000011) << 4); 379 PORTC = (PORTC & ~B01000000) 380 | (((color) & B00100000) << 1); 381 PORTE = (PORTE & ~B01000000) | (((color) & 382 B10000000) >> 1); 383 384 uint16_t x; 385 x=38400; // 240*320/2PORTF = ; // 386 WR 0 387 byte wr0= PORTF & B10111111; // set WR 0 388 byte wr1= PORTF | B01000000; 389 // set WR 1 390 for(uint16_t y=0;y<x;y++) 391 { 392 PORTF = wr0; 393 PORTF 394 = wr1; 395 PORTF = wr0; 396 PORTF = wr1; 397 398 PORTF = wr0; 399 PORTF 400 = wr1; 401 PORTF = wr0; 402 PORTF = wr1; 403 } 404} 405 406void Display_integer(int16_t 407 n) { 408 String str=String(n); 409 byte l=str.length(); 410 char b[l+1]; // 411 +1 for the null terminator 412 str.toCharArray(b,l+1); 413 for(int n=0; n<l; n++) 414 { 415 Display_char(b[n]); 416 } 417} 418 419void Display_string(String str) 420 { 421 byte l=str.length(); 422 char b[l+1]; // +1 for the null terminator 423 424 str.toCharArray(b,l+1); 425 for(int n=0; n<l; n++) { 426 Display_char(b[n]); 427 428 } 429} 430 431void Display_char(char znak) { 432 static const byte ASCII[][5] 433 = 434 { 435 {0x00, 0x00, 0x00, 0x00, 0x00}, // 20 436 {0x00, 0x00, 0x5f, 437 0x00, 0x00}, // 21 ! 438 {0x00, 0x07, 0x00, 0x07, 0x00}, // 22 " 439 {0x14, 440 0x7f, 0x14, 0x7f, 0x14}, // 23 # 441 {0x24, 0x2a, 0x7f, 0x2a, 0x12} ,// 24 $ 442 443 {0x23, 0x13, 0x08, 0x64, 0x62}, // 25 % 444 {0x36, 0x49, 0x55, 0x22, 0x50}, 445 // 26 & 446 {0x00, 0x00, 0x07, 0x05, 0x07}, // 27 ' 447 {0x00, 0x1c, 0x22, 448 0x41, 0x00}, // 28 ( 449 {0x00, 0x41, 0x22, 0x1c, 0x00}, // 29 ) 450 {0x14, 451 0x08, 0x3e, 0x08, 0x14}, // 2a * 452 {0x08, 0x08, 0x3e, 0x08, 0x08}, // 2b + 453 454 {0x00, 0x50, 0x30, 0x00, 0x00}, // 2c , 455 {0x08, 0x08, 0x08, 0x08, 0x08}, 456 // 2d - 457 {0x00, 0x60, 0x60, 0x00, 0x00}, // 2e . 458 {0x20, 0x10, 0x08, 459 0x04, 0x02}, // 2f / 460 {0x3e, 0x51, 0x49, 0x45, 0x3e}, // 30 0 461 {0x00, 462 0x42, 0x7f, 0x40, 0x00}, // 31 1 463 {0x42, 0x61, 0x51, 0x49, 0x46}, // 32 2 464 465 {0x21, 0x41, 0x45, 0x4b, 0x31}, // 33 3 466 {0x18, 0x14, 0x12, 0x7f, 0x10}, 467 // 34 4 468 {0x27, 0x45, 0x45, 0x45, 0x39}, // 35 5 469 {0x3c, 0x4a, 0x49, 470 0x49, 0x30}, // 36 6 471 {0x01, 0x71, 0x09, 0x05, 0x03}, // 37 7 472 {0x36, 473 0x49, 0x49, 0x49, 0x36}, // 38 8 474 {0x06, 0x49, 0x49, 0x29, 0x1e}, // 39 9 475 476 {0x00, 0x36, 0x36, 0x00, 0x00}, // 3a : 477 {0x00, 0x56, 0x36, 0x00, 0x00}, 478 // 3b ; 479 {0x08, 0x14, 0x22, 0x41, 0x00}, // 3c < 480 {0x14, 0x14, 0x14, 481 0x14, 0x14}, // 3d = 482 {0x00, 0x41, 0x22, 0x14, 0x08}, // 3e > 483 {0x02, 484 0x01, 0x51, 0x09, 0x06}, // 3f ? 485 {0x32, 0x49, 0x79, 0x41, 0x3e}, // 40 @ 486 487 {0x7e, 0x11, 0x11, 0x11, 0x7e}, // 41 A 488 {0x7f, 0x49, 0x49, 0x49, 0x36}, 489 // 42 B 490 {0x3e, 0x41, 0x41, 0x41, 0x22}, // 43 C 491 {0x7f, 0x41, 0x41, 492 0x22, 0x1c}, // 44 D 493 {0x7f, 0x49, 0x49, 0x49, 0x41}, // 45 E 494 {0x7f, 495 0x09, 0x09, 0x09, 0x01}, // 46 F 496 {0x3e, 0x41, 0x49, 0x49, 0x7a}, // 47 G 497 498 {0x7f, 0x08, 0x08, 0x08, 0x7f}, // 48 H 499 {0x00, 0x41, 0x7f, 0x41, 0x00}, 500 // 49 I 501 {0x20, 0x40, 0x41, 0x3f, 0x01}, // 4a J 502 {0x7f, 0x08, 0x14, 503 0x22, 0x41}, // 4b K 504 {0x7f, 0x40, 0x40, 0x40, 0x40}, // 4c L 505 {0x7f, 506 0x02, 0x0c, 0x02, 0x7f}, // 4d M 507 {0x7f, 0x04, 0x08, 0x10, 0x7f}, // 4e N 508 509 {0x3e, 0x41, 0x41, 0x41, 0x3e}, // 4f O 510 {0x7f, 0x09, 0x09, 0x09, 0x06}, 511 // 50 P 512 {0x3e, 0x41, 0x51, 0x21, 0x5e}, // 51 Q 513 {0x7f, 0x09, 0x19, 514 0x29, 0x46}, // 52 R 515 {0x46, 0x49, 0x49, 0x49, 0x31}, // 53 S 516 {0x01, 517 0x01, 0x7f, 0x01, 0x01}, // 54 T 518 {0x3f, 0x40, 0x40, 0x40, 0x3f}, // 55 U 519 520 {0x1f, 0x20, 0x40, 0x20, 0x1f}, // 56 V 521 {0x3f, 0x40, 0x38, 0x40, 0x3f}, 522 // 57 W 523 {0x63, 0x14, 0x08, 0x14, 0x63}, // 58 X 524 {0x07, 0x08, 0x70, 525 0x08, 0x07}, // 59 Y 526 {0x61, 0x51, 0x49, 0x45, 0x43}, // 5a Z 527 {0x00, 528 0x7f, 0x41, 0x41, 0x00}, // 5b [ 529 {0x02, 0x04, 0x08, 0x10, 0x20}, // 5c Y 530 531 {0x00, 0x41, 0x41, 0x7f, 0x00}, // 5d ] 532 {0x04, 0x02, 0x01, 0x02, 0x04}, 533 // 5e ^ 534 {0x40, 0x40, 0x40, 0x40, 0x40}, // 5f _ 535 {0x00, 0x01, 0x02, 536 0x04, 0x00}, // 60 ` 537 {0x20, 0x54, 0x54, 0x54, 0x78}, // 61 a 538 {0x7f, 539 0x48, 0x44, 0x44, 0x38}, // 62 b 540 {0x38, 0x44, 0x44, 0x44, 0x20}, // 63 c 541 542 {0x38, 0x44, 0x44, 0x48, 0x7f}, // 64 d 543 {0x38, 0x54, 0x54, 0x54, 0x18}, 544 // 65 e 545 {0x08, 0x7e, 0x09, 0x01, 0x02}, // 66 f 546 {0x0c, 0x52, 0x52, 547 0x52, 0x3e}, // 67 g 548 {0x7f, 0x08, 0x04, 0x04, 0x78}, // 68 h 549 {0x00, 550 0x44, 0x7d, 0x40, 0x00}, // 69 i 551 {0x20, 0x40, 0x44, 0x3d, 0x00}, // 6a j 552 553 {0x7f, 0x10, 0x28, 0x44, 0x00}, // 6b k 554 {0x00, 0x41, 0x7f, 0x40, 0x00}, 555 // 6c l 556 {0x7c, 0x04, 0x18, 0x04, 0x78}, // 6d m 557 {0x7c, 0x08, 0x04, 558 0x04, 0x78}, // 6e n 559 {0x38, 0x44, 0x44, 0x44, 0x38}, // 6f o 560 {0x7c, 561 0x14, 0x14, 0x14, 0x08}, // 70 p 562 {0x08, 0x14, 0x14, 0x18, 0x7c}, // 71 q 563 564 {0x7c, 0x08, 0x04, 0x04, 0x08}, // 72 r 565 {0x48, 0x54, 0x54, 0x54, 0x20}, 566 // 73 s 567 {0x04, 0x3f, 0x44, 0x40, 0x20}, // 74 t 568 {0x3c, 0x40, 0x40, 569 0x20, 0x7c}, // 75 u 570 {0x1c, 0x20, 0x40, 0x20, 0x1c}, // 76 v 571 {0x3c, 572 0x40, 0x30, 0x40, 0x3c}, // 77 w 573 {0x44, 0x28, 0x10, 0x28, 0x44}, // 78 x 574 575 {0x0c, 0x50, 0x50, 0x50, 0x3c}, // 79 y 576 {0x44, 0x64, 0x54, 0x4c, 0x44}, 577 // 7a z 578 {0x00, 0x08, 0x36, 0x41, 0x00}, // 7b { 579 {0x00, 0x00, 0x7f, 580 0x00, 0x00}, // 7c | 581 {0x00, 0x41, 0x36, 0x08, 0x00}, // 7d } 582 {0x10, 583 0x08, 0x08, 0x10, 0x08}, // 7e 584 {0x00, 0x06, 0x09, 0x09, 0x06} // 7f 585 586 }; 587 588 int8_t size=F_SIZE; 589 int16_t color=F_COLOR; 590 int16_t bcolor=B_COLOR; 591 592 593 if( (P_COL+(size*6)) > 319) { 594 P_COL=0; 595 P_ROW+=size*(8+1); 596 597 } 598 599 LCD_command_write(0x2a); // ROWS 600 LCD_data_write(P_ROW>>8); 601 602 LCD_data_write(P_ROW); 603 LCD_data_write(((P_ROW+size*8)-1)>>8); 604 LCD_data_write((P_ROW+size*8)-1); 605 606 LCD_command_write(0x2b); // COLUMNS 607 LCD_data_write(P_COL>>8); 608 LCD_data_write(P_COL); 609 610 LCD_data_write((P_COL+(size*6))>>8); 611 LCD_data_write(P_COL+(size*6)); 612 613 LCD_command_write(0x2c); 614 byte bchigh=bcolor >> 8; 615 byte bclow=bcolor; 616 617 byte fchigh=color >> 8; 618 byte fclow=color; 619 byte index, nbit, i, j; 620 621 for (index = 0; index < 5; index++) { 622 char col=ASCII[znak - 0x20][index]; 623 624 for ( i=0; i<size; i++){ 625 byte mask=B00000001; 626 for (nbit = 627 0; nbit < 8; nbit++) { 628 if (col & mask) { 629 for (j=0; j<size; 630 j++){ 631 LCD_data_write(fchigh); 632 LCD_data_write(fclow); 633 634 } 635 } 636 else { 637 for (j=0; j<size; j++){ 638 639 LCD_data_write(bchigh); 640 LCD_data_write(bclow); 641 } 642 643 } 644 mask=mask<<1; 645 } 646 } 647 } 648 P_COL+=size*6; 649 650} 651 652void Display_clear_char(byte n) { 653 // delete n chars 654 int8_t 655 size=F_SIZE; 656 int16_t bcolor=B_COLOR; 657 658 LCD_command_write(0x2a); // 659 ROWS 660 LCD_data_write(P_ROW>>8); 661 LCD_data_write(P_ROW); 662 LCD_data_write(((P_ROW+size*8)-1)>>8); 663 664 LCD_data_write((P_ROW+size*8)-1); 665 LCD_command_write(0x2b); // COLUMNS 666 667 LCD_data_write(P_COL>>8); 668 LCD_data_write(P_COL); 669 LCD_data_write((P_COL+(size*6*n))>>8); 670 671 LCD_data_write(P_COL+(size*6*n)); 672 LCD_command_write(0x2c); 673 674 byte 675 bchigh=bcolor >> 8; 676 byte bclow=bcolor; 677 int16_t cyc=size*8 * size*6*n; 678 679 for (int16_t i=0; i<cyc; i++) { 680 LCD_data_write(bchigh); 681 LCD_data_write(bclow); 682 683 } 684} 685 686byte ReadTouch(void) { 687 //Y1 A3 A2 688 //X1 A2 A1 689 //Y2 690 9 6 691 //X2 8 7 692 int16_t row, col; 693 int8_t touch, wait_touch, valid; 694 695 wait_touch=1; 696 valid=0; 697 PORTF = PORTF | B00010000; // CS 1 698 while 699 (wait_touch) { 700 pinMode(Y1, INPUT); 701 pinMode(Y2, INPUT_PULLUP); 702 703 704 pinMode(X1, OUTPUT); 705 pinMode(X2, OUTPUT); 706 digitalWrite(X1, 707 LOW); 708 digitalWrite(X2, LOW); 709 710 touch = !digitalRead(Y1); // 711 0 - touched 712 if (touch) { 713 //delay(5); 714 digitalWrite(X1, HIGH); 715 // X variant A 716 //digitalWrite(X2, HIGH); // X variant B 717 delay(1); 718 719 row = analogRead(Y1); 720 delay(4); 721 if (abs(analogRead(Y1)-row)>3) 722 { return 0;} 723 delay(3); 724 if (abs(analogRead(Y1)-row)>3) { return 725 0;} 726 //if (analogRead(Y1)!=row) { return 0;} 727 728 pinMode(X1, 729 INPUT); 730 pinMode(X2, INPUT_PULLUP); 731 732 pinMode(Y1, OUTPUT); 733 734 pinMode(Y2, OUTPUT); 735 //digitalWrite(Y1, HIGH); // Y variant A 736 737 //digitalWrite(Y2, LOW); // Y variant A 738 digitalWrite(Y1, LOW); // 739 Y variant B 740 digitalWrite(Y2, HIGH); // Y variant B 741 delay(1); 742 743 col = analogRead(X1); 744 delay(4); 745 if (abs(analogRead(X1)-col)>3) 746 { return 0;} 747 delay(3); 748 if (abs(analogRead(X1)-col)>3) { return 749 0;} 750 //if (analogRead(X1)!=col) { return 0;} 751 752 //digitalWrite(Y1, 753 LOW); // Y variant A 754 digitalWrite(Y2, LOW); // Y variant B 755 //delay(5); 756 757 touch = !digitalRead(X1); // 0 - dotyk 758 if (touch) { 759 int16_t 760 rows=ROW_L-ROW_F; 761 int16_t cols=COL_L-COL_F; 762 float row1=float(row-ROW_F)/rows*240; 763 764 float col1=float(col-COL_F)/cols*320; 765 T_ROW=int(row1); 766 T_COL=int(col1); 767 768 valid=1; 769 } 770 wait_touch=0; 771 } 772 } 773 // Re-Set 774 A2 A3 8 9 for ILI9341 775 BD_as_output(); 776 DDRF = DDRF | B11110010; // A0-A4 777 as outputs 778 PORTF = PORTF & B11101111; // CS 0 779 // To find out values 780 for calibration F_ROW, L_ROW, F_COL, F_COL 781 /* //uncomment to have the coordinates 782 of a touch displayed 783 B_COLOR=0x0C0C; 784 F_SIZE=2; 785 P_COL=230; 786 P_ROW=200; 787 788 Display_integer(row); 789 P_COL=280; 790 P_ROW=200; 791 Display_integer(col); 792 793 794 P_COL=230; 795 P_ROW=220; 796 Display_clear_char(3); 797 Display_integer(T_ROW); 798 799 P_COL=280; 800 P_ROW=220; 801 Display_clear_char(3); 802 Display_integer(T_COL); 803 804 B_COLOR=GREEN; 805 F_SIZE=3; 806 */ 807 // Draw a point where touched 808// 809 LCD_rect(T_COL-1,T_ROW-1, 2, 2,F_COLOR); 810 T_ROW = row; 811 T_COL = col; 812 813 return valid; 814} 815 816uint16_t D_COL, D_ROW; 817 818void setup() 819{ 820 821 // Serial.begin(115200); 822 delay(200); 823// Serial.println("Start init"); 824 825 // Set pins 1-8 as output 826 BD_as_output(); 827 828 // Set pins A0-A4 as 829 output 830 DDRC = DDRC | B00011111; 831 832 LCD_init(); 833 834 LCD_clear(0x0C); 835 836 837 B_COLOR=0x0c0c; 838 F_COLOR=BLACK; 839//(col,row,width,height,color),left 840 //reference for the call parameters 841 LCD_triangle(115,75,100,100,BLUE,false); 842 //play button 843 LCD_rect(122,128,40,10, WHITE); //pause, is in the play button, 844 so written 2nd 845 LCD_rect(122,112,40,10, WHITE); //pause 846 LCD_triangle(230,105,40,40,RED,false); 847 //skip forward 848 LCD_triangle(270,105,40,40,RED,false); //skip forward 849 LCD_rect(310,105,5,40, 850 RED); //skip bar 851 LCD_triangle(10,105,40,40,RED,true); //skip back 852 LCD_triangle(50,105,40,40,RED,true); 853 //skip back 854 LCD_rect(5,105,5,40, RED); //skip bar 855 LCD_rect(200,30,40,10, 856 YELLOW); //plus volume - 857 LCD_rect(215,15,10,40, YELLOW); //plus volume | 858 859 LCD_rect(80,30,40,10, YELLOW); //minus volume - 860 LCD_rect(290,210,30,30, MAGENTA); 861 //cursor corner lower left 862 LCD_rect(0,210,30,30, MAGENTA); //cursor corner 863 lower right 864//sketch uses 6% more storage and 4% more RAM with USB functionality 865 866 Mouse.begin(); 867 Keyboard.begin(); 868} 869#define VK_MUTE 0xE2 //no 870 'button' for this, I just push pause 871#define VK_VOL_DOWN 0xEA 872#define 873 VK_VOL_UP 0xE9 874#define VK_SKIP_FORWARD 0xB5 875#define VK_SKIP_BACKWARD 876 0xB6 877#define VK_STOP 0xB7 878#define VK_PLAY_PAUSE 0xCD 879#define 880 VK_MOUSE_LR 0 881#define VK_MOUSE_UL 1 882 883const int16_t y_button_centers[] 884 = {550,550,550,250,250,840,840 }; 885const int16_t x_button_centers[] = {470,760,250,630,370,840,130 886 }; 887const uint8_t virtual_keys[] = { VK_PLAY_PAUSE, VK_SKIP_FORWARD, VK_SKIP_BACKWARD, 888 VK_VOL_UP, 889 VK_VOL_DOWN, VK_MOUSE_LR,0x1 }; 890 891void 892 loop() 893{ 894 byte touch=ReadTouch() ; 895 if(touch) { 896 uint16_t Current_error 897 = 1000; 898 uint8_t index = 0; 899 for (int i=0; i<sizeof(virtual_keys); i++) 900 { 901 uint16_t error = abs((int)T_COL - x_button_centers[i]) + abs(T_ROW - 902 y_button_centers[i]); 903 if (error < Current_error){ 904 index = i; 905 906 Current_error = error; 907 } 908 } 909 if (Current_error < 99){ 910 //if the touch is within 100 'point' (total) error of the defined points, it is 911 a valid key press 912 LCD_command_write(0x21); //on a valid keypress the 913 screen colors are inverted, just user feedback 914 switch (virtual_keys[index]){ 915 916 case VK_MOUSE_LR: //this corresponds to the lower right rectangle, it 917 puts the mouse in the lower right corner to keep the (Mac) computer from sleeping 918 919 for (uint8_t j = 0; j < 10; j++){ 920 Mouse.move(75, 921 75); 922 delay(5); 923 } 924 break; 925 case 926 VK_MOUSE_UL: //this moves the mouse up and left, to wake the computer or take the 927 cursor out of the corner to allow standby 928 Mouse.move(-25, -25); 929 930 break; 931 default: 932 Consumer.write(virtual_keys[index]); 933 934 break; 935 936 } 937 delay(100); 938 939 LCD_command_write(0x20); //return the LCD to normal colors. 940 } 941 942 delay(10); 943 944 } 945} 946
Downloadable files
assembly
Its just a LCD plugged into a Leonardo, the Leonardo is in a case that allows access to the connetors
assembly

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

Assembly
Assembly

Comments
Only logged in users can leave comments