Внизу представлен код программы для Arduino Uno и сенсорного TFT LCD экрана. Данная программа содержит несколько подпрограмм, придающие LCD-дисплею, подключенную к Arduino UNO, внешний вид операционной системы Windows 9x. В ней имеется рабочий стол с ярлыком на калькулятор. Так же имеется панель задач и меню «Пуск». При нажатии на меню «Пуск» открывается меню с возможностью запуска нужного приложения из доступных. На данный момент имеются только три приложения:
Меню «Пуск» и внешний вид рабочего стола
- графический редактор;
- Калькулятор;
- Игра пинпонг.
Запущенная игра
Конец игры
Калькулятор
Графический редактор
Завершение работы
Выключение компьютера
Разумеется эти приложения максимально упрощены.
#include <Adafruit_GFX.h> // Core graphics library #include <Adafruit_TFTLCD.h> // Hardware-specific library #include <TouchScreen.h> #if defined(__SAM3X8E__) #undef __FlashStringHelper::F(string_literal) #define F(string_literal) string_literal #endif //Определение граничных значений сенсора #define TS_MINX 150 #define TS_MINY 120 #define TS_MAXX 920 #define TS_MAXY 940 //Определение выводов дисплея #define YP A3 // must be an analog pin, use "An" notation! #define XM A2 // must be an analog pin, use "An" notation! #define YM 9 // can be a digital pin #define XP 8 // can be a digital pin TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300); #define LCD_CS A3 #define LCD_CD A2 #define LCD_WR A1 #define LCD_RD A0 // optional #define LCD_RESET A4 // Определение цветов: #define BLACK 0x0000 #define BLUE 0x001F #define RED 0xF800 #define GREEN 0x07E0 #define CYAN 0x07FF #define MAGENTA 0xF81F #define YELLOW 0xFFE0 #define WHITE 0xFFFF #define GRAY 0b1000010000010000 #define LIGHTGRAY 0b1110011100011100 //Объявления объекта дисплея Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET); //int oldcolor, currentcolor; int xm; int ym; bool nazh; bool nazh1; void(* resetFunc) (void) = 0;//объявление функцию reset с адресом 0 void form(int x1,int y1,int x2,int y2, String caption){//Windows-форма //tft.fillRect(x1, y1, x2, 30, LIGHTGRAY); tft.fillRect(x1+1, y1+1, x2-1, 29, BLUE);//Заголовок окна tft.drawRect(x1, y1, x2, 30, LIGHTGRAY); tft.fillRect(x1+x2-30, y1+1, 29, 28, RED);//Кнопка закрытия окна tft.setCursor(x1+x2-24, y1-3); tft.setTextColor(WHITE); tft.setTextSize(4); tft.print('x'); tft.setCursor(x1+14, y1+6);//Вывод заголовка окна tft.setTextColor(WHITE); tft.setTextSize(2); tft.print(caption); tft.fillRect(x1+1, y1+31, x2-1, y2, LIGHTGRAY);//Само окно } void button(int x,int y,int w,int h, String caption, bool cl){//Кнопка tft.fillRect(x+1, y+1, w-2, h-2, LIGHTGRAY); if (cl){//RКогда она нажата tft.drawFastHLine(x, y,w,GRAY); tft.drawFastHLine(x, y+h,w,WHITE); tft.drawFastVLine(x, y,h,GRAY); tft.drawFastVLine(x+w, y,h,WHITE); tft.setCursor(x+4, y+3); tft.setTextColor(YELLOW); tft.setTextSize(2); tft.print(caption); } else {//Когда она отпущена tft.drawFastHLine(x, y,w,WHITE); tft.drawFastHLine(x, y+h,w,GRAY); tft.drawFastVLine(x, y,h,WHITE); tft.drawFastVLine(x+w, y,h,GRAY); tft.setCursor(x+4, y+3); tft.setTextColor(BLACK); tft.setTextSize(2); tft.print(caption); } } void edit(int x,int y,int w, String caption){//Однострочный редактор tft.fillRect(x+1, y+1, w-2, 25, YELLOW); tft.drawFastHLine(x, y,w,GRAY); tft.drawFastHLine(x, y+25,w,WHITE); tft.drawFastVLine(x, y,25,GRAY); tft.drawFastVLine(x+w, y,25,WHITE); tft.setCursor(x+4, y+3); tft.setTextColor(BLACK); tft.setTextSize(2); tft.print(caption); } #define MINPRESSURE 10 #define MAXPRESSURE 1000 bool ButtonNazh(int x,int y,int w,int h, String caption){//Для отслежживания события нажатия на кнопку if ((xm>x)&&(xm<x+w)&&(ym>y)&&(ym<y+h)&&nazh) { button(x,y,w,h, caption, 1); delay(300); button(x,y,w,h, caption, 0); return(1); } else return(0); } bool CE=1; void events(){//Слежение за событиями вообще pinMode(13, OUTPUT); digitalWrite(13, HIGH); TSPoint p = ts.getPoint();//Считывание из сенсора экрана digitalWrite(13, LOW); pinMode(XM, OUTPUT); pinMode(YP, OUTPUT); nazh1=nazh; nazh=p.z > MINPRESSURE && p.z < MAXPRESSURE; p.x = map(p.x, TS_MINX, TS_MAXX, tft.width(), 0); p.y = map(p.y, TS_MINY, TS_MAXY, tft.height(), 0); xm=p.x;//x-координата нажатия ym=p.y;//y-координата нажатия } void ShowMessage(String msg){//вывод небольших сообщений в окне. form(30, 100, 180, 100, ""); tft.setCursor(40, 150); tft.setTextColor(BLACK); tft.setTextSize(2); tft.print(msg); button(70, 180, 90, 30, " Ok", false); CE=false; while (not CE){ events(); CE=ButtonNazh(70, 180, 90, 30, " Ok"); CE=CE||((nazh)&&(xm>180)&&(xm<210)&&(ym>100)&&(ym<130)); } } void Pinpong(){//Игра пинпонг int px=100; int py=280; int shx=100; int shy=100; int vx=2; int vy=2; int r=10; form(1,0,240,319,"Pinpong.EXE"); tft.fillRect(3, 35, 235, 290, WHITE); tft.fillRect(px, py, 50, 10, RED); CE=false; while (not CE){ events(); CE=nazh && xm>211 && ym< 28; if ((nazh)&&(xm<100)){ tft.fillRect(px, py, 50, 10, WHITE); px=px-5; if (px<0) px=0; tft.fillRect(px, py, 50, 10, RED); } if ((nazh)&&(xm>120)){ tft.fillRect(px, py, 50, 10, WHITE); px=px+5; if (px>190) px=190; tft.fillRect(px, py, 50, 10, RED); } tft.fillRect(shx, shy, r, r, WHITE); shx=shx+vx; shy=shy+vy; tft.fillRect(shx, shy, r, r, BLUE); if ((shx>235)||(shx<5)) vx=-vx; if (shy<35) vy=-vy; if ((shy>py-r)&&(shy<py+r)&&(shx>px)&&(shx<px+50)) vy=-vy; delay(20); if (shy>py+r) { ShowMessage ("Game Over"); Pinpong(); } } resetFunc(); } void desktop(){//Рабочий стол tft.fillScreen(CYAN); button(0,290,240,30,"",0); button(2,292,65,25,"Start",0); button(80,100,45,65,"",0); tft.fillRect(90, 110, 30, 5, YELLOW); edit (50,175,100,"CALC.EXE") ; } void setup(void) { tft.reset();//Сброс дисплея uint16_t identifier = tft.readID(); tft.begin(identifier);//Инициализация дисплея desktop();//Прорисовка рабочего стола } long ch=0; long ch1=0; int dey=0; long calc(){ switch (dey){ case 0: ch=ch1; break; case 1: ch=ch+ch1; break; case 2: ch=ch-ch1; break; case 3: ch=ch*ch1; break; case 4: ch=ch/ch1; break; } ch1=0; edit(15,50,200,String(ch)); } void CalcEXE(){//Калькулятор form(1,0,240,280,"Calc.EXE"); for (int i=1; i<10; i++) { int x=(i-1)%3*60+7; int y=(i-1)/3*30+180; button(x,y,55,25,String(i),0); } button(185,180,50,25,"+",0); button(185,210,50,25,"-",0); button(185,240,50,25,"*",0); button(185,270,50,25,"/",0); button(7,270,55,25,"0",0); button(67,270,115,25,"=",0); button(7,150,115,25,"C",0); edit(15,50,200,""); CE=false; while (not CE){ events(); CE=nazh && xm>211 && ym< 28; for (int i=1; i<10; i++) { int x=(i-1)%3*60+7; int y=(i-1)/3*30+180; if (ButtonNazh(x,y,55,25,String(i))) { ch1=ch1*10+i; edit(15,50,200,String(ch1)); } } if (ButtonNazh(185,180,50,25,"+")){ calc(); dey=1; }; if (ButtonNazh(185,210,50,25,"-")){ calc(); dey=2; }; if (ButtonNazh(185,240,50,25,"*")){ calc(); dey=3; }; if (ButtonNazh(185,270,50,25,"/")){ calc(); dey=4; }; if (ButtonNazh(7,270,55,25,"0")){ ch1=ch1*10; edit(15,50,200,String(ch1)); }; if (ButtonNazh(67,270,115,25,"=")){ calc(); }; if (ButtonNazh(7,150,115,25,"C")){ ch1=0; ch=0; dey=0; edit(15,50,200,""); }; } ch1=0; ch=0; dey=0; resetFunc(); } void MSPaintEXE(){//Графический редактор int colors[6]={RED, YELLOW, GREEN, CYAN, BLUE, MAGENTA}; form(1,0,240,319,"Paint.EXE"); tft.fillRect(5, 35, 230, 240, WHITE); for (int i=0; i<7; i++){ tft.fillRect(i*40, 280, 40, 40, colors[i]); } int currentcolor = RED; CE=false; while (not CE){ events(); CE=nazh && xm>211 && ym< 28; for (int i=0; i<7; i++) if (nazh && xm>i*40 && ym>280 && xm< i*40+40){ currentcolor=colors[i]; tft.drawRect(i*40, 280, 40, 40, WHITE); } if (nazh && xm>5 && ym>35 && xm<5+230 && ym<35+240) tft.fillRect(xm-2,ym-2,4,4,currentcolor); } resetFunc(); } void shutdoun(){//Завершение работы desktop(); form(20,40,200,150,"Shutdown"); button(40,80,150,30,"Shutdown",0); button(40,115,150,30,"Restart",0); button(40,160,150,30,"Cancel",0); CE=false; while (not CE){ events(); CE=nazh && xm>200 && xm<220 && ym>40 && ym < 60; if (ButtonNazh(40,80,150,30,"Shutdown")){//Выключение tft.fillScreen(BLACK); tft.setCursor(20, 100); tft.setTextColor(RED); tft.setTextSize(2); tft.print("It's now safe to "); tft.setCursor(20, 120); tft.print("turn off"); tft.setCursor(20, 140); tft.print("your computer"); while(1) {}; } CE=ButtonNazh(40,115,150,30,"Restart");//Перезагрузка CE=CE||ButtonNazh(40,160,150,30,"Cancel");//Отмена завершения работы } resetFunc();//Перезагрузка } void start(){//Меню пуск CE=false; button(20,262,125,25,"shutdown",0);//Элементы меню button(20,238,125,25,"Paint.exe",0); button(20,214,125,25,"Calc.exe",0); button(20,190,125,25,"Pinpong",0); tft.fillRect(1, 190, 19, 100, BLUE); while (not CE){ events(); CE=nazh; if (ButtonNazh(20,262,125,25,"shutdown")) shutdoun();//Отслеживание событий с меню пуск. if (ButtonNazh(20,238,125,25,"Paint.exe")) MSPaintEXE(); if (ButtonNazh(20,214,125,25,"Calc.exe")) CalcEXE(); if (ButtonNazh(20,190,125,25,"Pinpong")) Pinpong(); } desktop(); } void loop() { events(); if (nazh && xm>80 && ym> 100 && xm<125 && ym<165) CalcEXE();//Нажали ли на ярлык на рабочем столе if (ButtonNazh(2,292,65,25,"Start")) start();//Нажатие на пуск if (nazh&&(xm<65)&&(ym>270)) {//Нажатие на пуск доп. из-за кривого сенсора while (nazh){events();} start(); } }