├── settings.gradle ├── resources └── img │ └── arduino.png ├── .gitignore ├── src └── main │ ├── ExtHyperLinkListener.java │ └── Arduino_Interface.java ├── Arduino_libraries ├── XPT2046_Touchscreen.h ├── HX8347_kbv.h ├── XPT2046_Touchscreen.cpp └── HX8347_kbv.cpp ├── README.md ├── streamdeck.ino └── LICENSE /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'StreamDeck' -------------------------------------------------------------------------------- /resources/img/arduino.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tekks/Streamdeck/HEAD/resources/img/arduino.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .settings 3 | .project 4 | .gradle 5 | bin/ 6 | build/ 7 | gradle 8 | gradlew.bat -------------------------------------------------------------------------------- /src/main/ExtHyperLinkListener.java: -------------------------------------------------------------------------------- 1 | package main; 2 | 3 | import java.awt.Desktop; 4 | import java.io.IOException; 5 | import java.net.URI; 6 | import java.net.URISyntaxException; 7 | import javax.swing.JEditorPane; 8 | import javax.swing.event.HyperlinkEvent; 9 | import javax.swing.event.HyperlinkListener; 10 | 11 | class ExtHyperLinkListener implements HyperlinkListener { 12 | JEditorPane editorPane; 13 | 14 | public ExtHyperLinkListener(JEditorPane editorPane) { 15 | this.editorPane = editorPane; 16 | } 17 | 18 | public void hyperlinkUpdate(HyperlinkEvent hypev) { 19 | if (hypev.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) 20 | try { 21 | Desktop.getDesktop().browse(new URI(hypev.getURL().toString())); 22 | } catch (IOException | URISyntaxException e) { 23 | e.printStackTrace(); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /Arduino_libraries/XPT2046_Touchscreen.h: -------------------------------------------------------------------------------- 1 | #ifndef _XPT2046_Touchscreen_h_ 2 | #define _XPT2046_Touchscreen_h_ 3 | 4 | #include "Arduino.h" 5 | #include 6 | 7 | #if ARDUINO < 10600 8 | #error "Arduino 1.6.0 or later (SPI library) is required" 9 | #endif 10 | 11 | class TS_Point { 12 | public: 13 | TS_Point(void) : x(0), y(0), z(0) {} 14 | TS_Point(int16_t x, int16_t y, int16_t z) : x(x), y(y), z(z) {} 15 | bool operator==(TS_Point p) { return ((p.x == x) && (p.y == y) && (p.z == z)); } 16 | bool operator!=(TS_Point p) { return ((p.x != x) || (p.y != y) || (p.z != z)); } 17 | int16_t x, y, z; 18 | }; 19 | 20 | class XPT2046_Touchscreen { 21 | public: 22 | XPT2046_Touchscreen(uint8_t cspin, uint8_t tirq=255); 23 | bool begin(); 24 | TS_Point getPoint(); 25 | bool touched(); 26 | void readData(uint16_t *x, uint16_t *y, uint8_t *z); 27 | bool bufferEmpty(); 28 | uint8_t bufferSize() { return 1; } 29 | // protected: 30 | bool isrWake; 31 | 32 | private: 33 | void update(); 34 | uint8_t csPin, tirqPin; 35 | int16_t xraw, yraw, zraw; 36 | uint32_t msraw; 37 | }; 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [![version](https://img.shields.io/github/release/tekks/Streamdeck/all.svg?style=flat-square)](https://github.com/Tekks/Streamdeck/releases) 4 | [![GitHub last commit](https://img.shields.io/github/last-commit/tekks/Streamdeck.svg?style=flat-square)](https://github.com/Tekks/Streamdeck/commits/master) 5 | [![license](https://img.shields.io/github/license/tekks/Streamdeck.svg?style=flat-square)](https://github.com/Tekks/Streamdeck/blob/master/LICENSE) 6 | 7 | # Stream Deck 4 Arduino 8 | inspired by Elgato 9 | 10 | ### Used Libarys 11 | * [Adafruit GFX graphics core library](https://github.com/adafruit/Adafruit-GFX-Library) 12 | 13 | =============================== 14 | 15 | ### Used Hardware 16 | * ARDUINO LEONARDO ~ 18€ 17 | * 2.8 inch TFT Resistive Arduino Touch LCD Shield 320×240 ~ 19€ 18 | 19 | =============================== 20 | 21 | ### How to 22 | You can use the Arduino without the Java Application. 23 | *coming soon* 24 | 25 | =============================== 26 | 27 | 28 | ### Result 29 | 30 | 31 | -------------------------------------------------------------------------------- /Arduino_libraries/HX8347_kbv.h: -------------------------------------------------------------------------------- 1 | #ifndef HX8347_KBV_H_ 2 | #define HX8347_KBV_H_ 3 | 4 | #define USE_MBED 0 5 | 6 | #if ARDUINO < 165 7 | #define USE_GFX_KBV 8 | #include "ADA_GFX_kbv.h" 9 | #else 10 | #include "Adafruit_GFX.h" 11 | #endif 12 | 13 | class HX8347_kbv : public Adafruit_GFX { 14 | 15 | public: 16 | #if USE_MBED 17 | #if defined(TARGET_LPC1768) 18 | HX8347_kbv(PinName CS=p8, PinName RS=p7, PinName RST=p10); 19 | #else 20 | HX8347_kbv(PinName CS=D10, PinName RS=D7, PinName RST=D9); 21 | #endif 22 | #else 23 | HX8347_kbv(); 24 | #endif 25 | void reset(void); // you only need the constructor 26 | void begin(uint16_t ID = 0x7575); // you only need the constructor 27 | virtual void drawPixel(int16_t x, int16_t y, uint16_t color); // and these three 28 | void WriteCmdData(uint16_t cmd, uint16_t dat); // public methods !!! 29 | uint16_t color565(uint8_t r, uint8_t g, uint8_t b) { return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); } 30 | uint16_t readID(void) { return _lcd_ID; } 31 | 32 | virtual void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color); 33 | virtual void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) { fillRect(x, y, 1, h, color); } 34 | virtual void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) { fillRect(x, y, w, 1, color); } 35 | virtual void fillScreen(uint16_t color) { fillRect(0, 0, _width, _height, color); } 36 | virtual void setRotation(uint8_t r); 37 | virtual void invertDisplay(boolean i); 38 | 39 | uint16_t readReg(uint16_t reg); 40 | int16_t readGRAM(int16_t x, int16_t y, uint16_t *block, int16_t w, int16_t h); 41 | uint16_t readPixel(int16_t x, int16_t y) { uint16_t color; readGRAM(x, y, &color, 1, 1); return color; } 42 | void setAddrWindow(int16_t x, int16_t y, int16_t x1, int16_t y1); 43 | void pushColors(uint16_t *block, int16_t n, bool first); 44 | void pushColors(uint8_t *block, int16_t n, bool first); 45 | void pushColors(const uint8_t *block, int16_t n, bool first, bool bigend = false); 46 | void vertScroll(int16_t top, int16_t scrollines, int16_t offset); 47 | 48 | 49 | protected: 50 | 51 | private: 52 | #if USE_MBED 53 | SPI _spi; 54 | DigitalOut _lcd_pin_cs, _lcd_pin_rs, _lcd_pin_reset; 55 | #endif 56 | uint16_t _lcd_ID; 57 | }; 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /Arduino_libraries/XPT2046_Touchscreen.cpp: -------------------------------------------------------------------------------- 1 | #include "XPT2046_Touchscreen.h" 2 | 3 | #define Z_THRESHOLD 400 4 | #define Z_THRESHOLD_INT 75 5 | #define MSEC_THRESHOLD 3 6 | #define SPI_SETTING SPISettings(2000000, MSBFIRST, SPI_MODE0) 7 | 8 | XPT2046_Touchscreen::XPT2046_Touchscreen(uint8_t cs, uint8_t tirq) 9 | { 10 | csPin = cs; 11 | tirqPin = tirq; 12 | msraw = 0x80000000; 13 | xraw = 0; 14 | yraw = 0; 15 | zraw = 0; 16 | isrWake = true; 17 | } 18 | 19 | static XPT2046_Touchscreen *isrPinptr; 20 | void isrPin(void); 21 | 22 | bool XPT2046_Touchscreen::begin() 23 | { 24 | SPI.begin(); 25 | pinMode(csPin, OUTPUT); 26 | digitalWrite(csPin, HIGH); 27 | if (255 != tirqPin) { 28 | pinMode( tirqPin, INPUT ); 29 | attachInterrupt(digitalPinToInterrupt(tirqPin), isrPin, FALLING); 30 | isrPinptr = this; 31 | } 32 | return true; 33 | } 34 | 35 | void isrPin( void ) 36 | { 37 | XPT2046_Touchscreen *o = isrPinptr; 38 | o->isrWake = true; 39 | } 40 | 41 | TS_Point XPT2046_Touchscreen::getPoint() 42 | { 43 | update(); 44 | return TS_Point(xraw, yraw, zraw); 45 | } 46 | 47 | bool XPT2046_Touchscreen::touched() 48 | { 49 | update(); 50 | return (zraw >= Z_THRESHOLD); 51 | } 52 | 53 | void XPT2046_Touchscreen::readData(uint16_t *x, uint16_t *y, uint8_t *z) 54 | { 55 | update(); 56 | *x = xraw; 57 | *y = yraw; 58 | *z = zraw; 59 | } 60 | 61 | bool XPT2046_Touchscreen::bufferEmpty() 62 | { 63 | return ((millis() - msraw) < MSEC_THRESHOLD); 64 | } 65 | 66 | static int16_t besttwoavg( int16_t x , int16_t y , int16_t z ) { 67 | int16_t da, db, dc; 68 | int16_t reta = 0; 69 | if ( x > y ) da = x - y; else da = y - x; 70 | if ( x > z ) db = x - z; else db = z - x; 71 | if ( z > y ) dc = z - y; else dc = y - z; 72 | 73 | if ( da <= db && da <= dc ) reta = (x + y) >> 1; 74 | else if ( db <= da && db <= dc ) reta = (x + z) >> 1; 75 | else reta = (y + z) >> 1; // else if ( dc <= da && dc <= db ) reta = (x + y) >> 1; 76 | 77 | return (reta); 78 | } 79 | 80 | // TODO: perhaps a future version should offer an option for more oversampling, 81 | // with the RANSAC algorithm https://en.wikipedia.org/wiki/RANSAC 82 | 83 | void XPT2046_Touchscreen::update() 84 | { 85 | int16_t data[6]; 86 | 87 | if (!isrWake) return; 88 | uint32_t now = millis(); 89 | if (now - msraw < MSEC_THRESHOLD) return; 90 | 91 | SPI.beginTransaction(SPI_SETTING); 92 | digitalWrite(csPin, LOW); 93 | SPI.transfer(0xB1 /* Z1 */); 94 | int16_t z1 = SPI.transfer16(0xC1 /* Z2 */) >> 3; 95 | int z = z1 + 4095; 96 | int16_t z2 = SPI.transfer16(0x91 /* X */) >> 3; 97 | z -= z2; 98 | if (z >= Z_THRESHOLD) { 99 | SPI.transfer16(0x91 /* X */); // dummy X measure, 1st is always noisy 100 | data[0] = SPI.transfer16(0xD1 /* Y */) >> 3; 101 | data[1] = SPI.transfer16(0x91 /* X */) >> 3; // make 3 x-y measurements 102 | data[2] = SPI.transfer16(0xD1 /* Y */) >> 3; 103 | data[3] = SPI.transfer16(0x91 /* X */) >> 3; 104 | } 105 | else data[0] = data[1] = data[2] = data[3] = 0; // Compiler warns these values may be used unset on early exit. 106 | data[4] = SPI.transfer16(0xD0 /* Y */) >> 3; // Last Y touch power down 107 | data[5] = SPI.transfer16(0) >> 3; 108 | digitalWrite(csPin, HIGH); 109 | SPI.endTransaction(); 110 | //Serial.printf("z=%d :: z1=%d, z2=%d ", z, z1, z2); 111 | if (z < 0) z = 0; 112 | if (z < Z_THRESHOLD) { // if ( !touched ) { 113 | // Serial.println(); 114 | zraw = 0; 115 | if (z < Z_THRESHOLD_INT) { // if ( !touched ) { 116 | if (255 != tirqPin) isrWake = false; 117 | } 118 | return; 119 | } 120 | zraw = z; 121 | 122 | // Average pair with least distance between each measured x then y 123 | //Serial.printf(" z1=%d,z2=%d ", z1, z2); 124 | //Serial.printf("p=%d, %d,%d %d,%d %d,%d", zraw, 125 | //data[0], data[1], data[2], data[3], data[4], data[5]); 126 | int16_t x = besttwoavg( data[0], data[2], data[4] ); 127 | int16_t y = besttwoavg( data[1], data[3], data[5] ); 128 | 129 | //Serial.printf(" %d,%d", x, y); 130 | //Serial.println(); 131 | if (z >= Z_THRESHOLD) { 132 | msraw = now; // good read completed, set wait 133 | xraw = x; 134 | yraw = y; 135 | } 136 | } 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /streamdeck.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Adafruit_GFX.h" 4 | #include 5 | #include "Keyboard.h" 6 | 7 | #define LCD_CS A3 8 | #define LCD_CD A2 9 | #define LCD_WR A1 10 | #define LCD_RD A0 11 | #define LCD_RESET A4 12 | #define TIRQ_PIN 3 13 | #define TFT_PIN 4 14 | 15 | uint8_t running; 16 | 17 | #define BLACK 0x0000 18 | #define BLUE 0x001F 19 | #define RED 0xF800 20 | #define GREEN 0x07E0 21 | #define CYAN 0x07FF 22 | #define MAGENTA 0xF81F 23 | #define YELLOW 0xFFE0 24 | #define WHITE 0xFFFF 25 | #define ORANGE 0xFD00 26 | 27 | #define KEY_F13 0xF0 28 | #define KEY_F14 0xF1 29 | #define KEY_F15 0xF2 30 | #define KEY_F16 0xF3 31 | #define KEY_F17 0xF4 32 | #define KEY_F18 0xF5 33 | #define KEY_F19 0xF6 34 | #define KEY_F20 0xF7 35 | #define KEY_F21 0xF8 36 | #define KEY_F22 0xF9 37 | #define KEY_F23 0xFA 38 | #define KEY_F24 0xFB 39 | 40 | boolean t1, t2, t3, t4, t5 , t6, t7, t8, t9, t10 , t11, t12; 41 | boolean t1h; 42 | XPT2046_Touchscreen tss(TFT_PIN, TIRQ_PIN); 43 | HX8347_kbv tft; 44 | 45 | uint16_t g_identifier; 46 | void setup(void) { 47 | Serial.begin(9600); 48 | Serial.setTimeout(50); 49 | tft.begin(g_identifier); 50 | g_identifier = tft.readID(); 51 | if (g_identifier == 0x00D3) g_identifier = 0x9486; 52 | if (g_identifier == 0xFFFF) g_identifier = 0x9341; 53 | initial(); 54 | Keyboard.begin(); 55 | tss.begin(); 56 | } 57 | 58 | void loop() { 59 | write_Jinput(); 60 | if (tss.touched()) { 61 | TS_Point p = tss.getPoint(); 62 | p.x = map(p.x, 320, 3850, 0, 480); 63 | p.y = map(p.y, 3800 , 305, 0, 320); 64 | 65 | //################## Code for actions here ################## 66 | //################## LINE 1 ################## 67 | if (p.x > 20 && p.x < 90 && p.y > 80 && p.y < 150) { 68 | if (t1) { 69 | draw_re(10, 60, GREEN, "DISC", "Mic", "ON"); 70 | draw_re(10, 120, GREEN, "DISC", "Speaker", "ON"); 71 | t6 = false; 72 | t1 = false; 73 | t1h = false; 74 | } else { 75 | if (t6) { 76 | t1h = false; 77 | } else { 78 | t1h = true; 79 | } 80 | draw_re(10, 60, RED, "DISC", "Mic", "OFF"); 81 | t1 = true; 82 | } 83 | Keyboard.write(KEY_F13); 84 | } 85 | if (p.x > 115 && p.x < 180 && p.y > 80 && p.y < 150) { 86 | if (t2) { 87 | draw_re(70, 60, GREEN, "TS", "Mic", "ON");; 88 | t2 = false; 89 | } else { 90 | draw_re(70, 60, RED, "TS", "Mic", "OFF"); 91 | t2 = true; 92 | } 93 | Keyboard.write(KEY_F15); 94 | } 95 | if (p.x > 200 && p.x < 275 && p.y > 80 && p.y < 150) { 96 | Keyboard.write(KEY_F17); 97 | } 98 | if (p.x > 290 && p.x < 365 && p.y > 80 && p.y < 150) { 99 | Keyboard.write(KEY_F18); 100 | } 101 | if (p.x > 385 && p.x < 455 && p.y > 80 && p.y < 150) { 102 | Keyboard.write(KEY_F19); 103 | } 104 | 105 | 106 | //################## LINE 2 ################## 107 | if (p.x > 20 && p.x < 90 && p.y > 165 && p.y < 235) { 108 | if (t6) { 109 | if (t1h == false) { 110 | draw_re(10, 60, GREEN, "DISC", "Mic", "ON"); 111 | t1 = false; 112 | } 113 | draw_re(10, 120, GREEN, "DISC", "Speaker", "ON"); 114 | t6 = false; 115 | } else { 116 | draw_re(10, 120, RED, "DISC", "Speaker", "OFF"); 117 | draw_re(10, 60, RED, "DISC", "Mic", "OFF"); 118 | t6 = true; 119 | t1 = true; 120 | } 121 | Keyboard.write(KEY_F14); 122 | } 123 | if (p.x > 115 && p.x < 180 && p.y > 165 && p.y < 235) { 124 | if (t7) { 125 | draw_re(70, 120, GREEN, "TS", "Speaker", "ON"); 126 | t7 = false; 127 | } else { 128 | draw_re(70, 120, RED, "TS", "Speaker", "OFF"); 129 | t7 = true; 130 | } 131 | Keyboard.write(KEY_F16); 132 | } 133 | if (p.x > 200 && p.x < 275 && p.y > 165 && p.y < 235) { 134 | } 135 | if (p.x > 290 && p.x < 365 && p.y > 165 && p.y < 235) { 136 | } 137 | if (p.x > 385 && p.x < 455 && p.y > 165 && p.y < 235) { 138 | } 139 | 140 | //################## LINE 3 ################## 141 | if (p.x > 20 && p.x < 90 && p.y > 245 && p.y < 315) { 142 | if (t11) { 143 | draw_re(10, 180, CYAN, "OBS", "Mic", "ON"); 144 | t11 = false; 145 | } else { 146 | draw_re(10, 180, RED, "OBS", "Mic", "OFF"); 147 | t11 = true; 148 | } 149 | Keyboard.write(KEY_F23); 150 | } 151 | if (p.x > 115 && p.x < 180 && p.y > 245 && p.y < 315) { 152 | if (t12) { 153 | draw_re(70, 180, CYAN, "OBS", "Speaker", "ON"); 154 | t12 = false; 155 | } else { 156 | draw_re(70, 180, RED, "OBS", "Speaker", "OFF"); 157 | t12 = true; 158 | } 159 | Keyboard.write(KEY_F24); 160 | } 161 | if (p.x > 200 && p.x < 275 && p.y > 245 && p.y < 315) { 162 | Keyboard.write(KEY_F20); 163 | } 164 | if (p.x > 290 && p.x < 365 && p.y > 245 && p.y < 315) { 165 | Keyboard.write(KEY_F21); 166 | } 167 | if (p.x > 385 && p.x < 455 && p.y > 245 && p.y < 315) { 168 | Keyboard.write(KEY_F22); 169 | } 170 | delay(500); 171 | } 172 | } 173 | 174 | void initial() { 175 | //################## Initial ################## 176 | tft.setRotation(3); 177 | tft.fillScreen(RED); 178 | tft.fillScreen(WHITE); 179 | tft.fillScreen(BLACK); 180 | tft.setTextColor(WHITE); 181 | 182 | draw_re(10, 60, GREEN, "DISC", "Mic", "ON"); 183 | draw_re(70, 60, GREEN, "TS", "Mic", "ON"); 184 | draw_re(130, 60, ORANGE, "OBS", "Scene", "Idle"); 185 | draw_re(190, 60, ORANGE, "OBS", "Timer", "ON/OFF"); 186 | draw_re(250, 60, ORANGE, "OBS", "Scene", "Active"); 187 | 188 | draw_re(10, 120, GREEN, "DISC", "Speaker", "ON"); 189 | draw_re(70, 120, GREEN, "TS", "Speaker", "ON"); 190 | draw_re(130, 120); 191 | draw_re(190, 120); 192 | draw_re(250, 120); 193 | 194 | draw_re(10, 180, CYAN, "OBS", "Mic", "ON"); 195 | draw_re(70, 180, CYAN, "OBS", "Speaker", "ON"); 196 | draw_re(130, 180, ORANGE, "OBS", "Scene", "OW"); 197 | draw_re(190, 180, ORANGE, "OBS", "Scene", "PUBG"); 198 | draw_re(250, 180, ORANGE, "OBS", "Scene", "SoW"); 199 | 200 | } 201 | 202 | void draw_re(int x, int y) { 203 | //Lenght: 32 + 20 = 52 204 | int dist = 10; 205 | tft.drawRect(x, y, 32 + 2 * dist, 32 + 2 * dist, WHITE); 206 | } 207 | 208 | void draw_re(int x, int y, uint16_t color, String txt1, String txt2, String txt3) { 209 | //Lenght: 32 + 20 = 52 210 | int dist = 10; 211 | int txtdst = 5; 212 | tft.drawRect(x, y, 32 + 2 * dist, 32 + 2 * dist, WHITE); 213 | tft.fillRect(x + 1, y + 1, 50, 50, BLACK); 214 | tft.setTextColor(color); 215 | tft.setTextSize(1); 216 | tft.setCursor(x + txtdst, y + txtdst); 217 | tft.println(txt1); 218 | tft.setCursor(x + txtdst, y + txtdst + 10); 219 | tft.println(txt2); 220 | tft.setCursor(x + txtdst, y + txtdst + 20); 221 | tft.println(txt3); 222 | } 223 | 224 | void write_Jinput() { 225 | String JString = Serial.readString(); 226 | tft.setTextSize(1); 227 | tft.setTextColor(WHITE); 228 | int x_desc = 5; 229 | int y_desc = 5; 230 | String count_items = getValue(JString, ';', 0); 231 | 232 | for (int i = 1; i < count_items.toInt() * 2; i = i + 2) { 233 | String string_desc = getValue(JString, ';', i); 234 | String string_item = getValue(JString, ';', i + 1); 235 | tft.fillRect(x_desc + 50, y_desc, 100, 7, BLACK); //x,y,l,h 236 | tft.setCursor(x_desc, y_desc); 237 | tft.println(string_desc); 238 | tft.setCursor(50 + x_desc, y_desc); 239 | tft.println(string_item); 240 | y_desc > 24 ? x_desc = x_desc + 150 : x_desc; 241 | y_desc > 24 ? y_desc = 5 : y_desc = y_desc + 10; 242 | } 243 | JString = ""; 244 | } 245 | 246 | String getValue(String data, char separator, int index) { 247 | int found = 0; 248 | int strIndex[] = { 0, -1 }; 249 | int maxIndex = data.length() - 1; 250 | for (int i = 0; i <= maxIndex && found <= index; i++) { 251 | if (data.charAt(i) == separator || i == maxIndex) { 252 | found++; 253 | strIndex[0] = strIndex[1] + 1; 254 | strIndex[1] = (i == maxIndex) ? i + 1 : i; 255 | } 256 | } 257 | return found > index ? data.substring(strIndex[0], strIndex[1]) : ""; 258 | } 259 | -------------------------------------------------------------------------------- /src/main/Arduino_Interface.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Andy Heil (Tekks). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package main; 17 | 18 | import java.awt.*; 19 | import java.awt.event.*; 20 | import java.io.PrintWriter; 21 | import java.net.InetAddress; 22 | import java.net.ServerSocket; 23 | import java.net.URL; 24 | import java.text.SimpleDateFormat; 25 | import java.util.Date; 26 | import javax.swing.*; 27 | import javax.swing.event.HyperlinkListener; 28 | 29 | 30 | 31 | import com.fazecast.jSerialComm.SerialPort; 32 | import oshi.SystemInfo; 33 | import oshi.hardware.CentralProcessor; 34 | 35 | /** 36 | * 37 | * @author Andy Heil (Tekks) 38 | */ 39 | 40 | public class Arduino_Interface { 41 | static SerialPort chosenPort; 42 | static JButton connectButton; 43 | static JComboBox portList; 44 | static String portListselect; 45 | static TrayIcon trayIcon; 46 | static JFrame window; 47 | private static final int PORT = 1258; 48 | 49 | public static void main(String[] args) { 50 | checkIfRunning(); 51 | try { 52 | UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); 53 | } catch (Exception ex) { 54 | ex.printStackTrace(); 55 | } 56 | UIManager.put("swing.boldMetal", Boolean.FALSE); 57 | SwingUtilities.invokeLater(new Runnable() { 58 | public void run() { 59 | createAndShowGUI(); 60 | } 61 | }); 62 | portList = new JComboBox(); 63 | } 64 | 65 | @SuppressWarnings("resource") 66 | private static void checkIfRunning() { 67 | try { 68 | new ServerSocket(PORT, 0, InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 })); 69 | } catch (Exception e) { 70 | e.printStackTrace(); 71 | JOptionPane.showMessageDialog(null, "Another Instance is Running", "Warning", JOptionPane.WARNING_MESSAGE); 72 | System.exit(1); 73 | } 74 | } 75 | 76 | private static void select_comport() { 77 | if (window != null) 78 | return; 79 | window = new JFrame(); 80 | window.setIconImage(createImage("/img/arduino.png", "tray icon")); 81 | window.setTitle("Arduino Interface | ComPort"); 82 | window.setSize(450, 100); 83 | window.setLayout(new BorderLayout()); 84 | window.setLocationRelativeTo(null); 85 | portList.removeAllItems(); 86 | SerialPort[] portNames = SerialPort.getCommPorts(); 87 | for (int i = 0; i < portNames.length; i++) { 88 | portList.addItem(portNames[i].getDescriptivePortName()); 89 | } 90 | if (chosenPort != null) { 91 | connectButton = new JButton("Deselect"); 92 | portList.setSelectedItem(portListselect); 93 | portList.setEnabled(false); 94 | } else { 95 | connectButton = new JButton("Select"); 96 | } 97 | 98 | JPanel topPanel = new JPanel(); 99 | topPanel.add(portList); 100 | topPanel.add(connectButton); 101 | window.add(topPanel, BorderLayout.NORTH); 102 | 103 | SystemInfo si = new SystemInfo(); 104 | CentralProcessor processor = si.getHardware().getProcessor(); 105 | connectButton.addActionListener(new ActionListener() { 106 | @Override 107 | public void actionPerformed(ActionEvent arg0) { 108 | if (connectButton.getText().equals("Select")) { 109 | String comport = portList.getSelectedItem().toString(); 110 | trayIcon.setToolTip("Connected: " + comport); 111 | portListselect = comport; 112 | comport = comport.substring(comport.indexOf("(") + 1); 113 | comport = comport.substring(0, comport.indexOf(")")); 114 | chosenPort = SerialPort.getCommPort(comport); 115 | chosenPort.setComPortTimeouts(SerialPort.TIMEOUT_SCANNER, 0, 0); 116 | if (chosenPort.openPort()) { 117 | connectButton.setText("Deselect"); 118 | portList.setEnabled(false); 119 | Thread thread = new Thread() { 120 | @Override 121 | public void run() { 122 | try { 123 | Thread.sleep(1000); 124 | } catch (Exception e) { 125 | e.printStackTrace(); 126 | } 127 | PrintWriter output = new PrintWriter(chosenPort.getOutputStream()); 128 | while (chosenPort != null) { 129 | 130 | String cpu = Double 131 | .toString((int) (processor.getSystemCpuLoad() * 100 * 100) / 100.00); 132 | String timestamp = new SimpleDateFormat("HH:mm:ss").format(new Date()); 133 | long availMem = si.getHardware().getMemory().getAvailable(); 134 | long totalMem = si.getHardware().getMemory().getTotal(); 135 | 136 | int threads = si.getOperatingSystem().getProcessCount(); 137 | 138 | String memory = (totalMem - availMem) * 100 / (int) Math.pow(1024, 3) / 100.00 139 | + " / " + totalMem * 100 / (int) Math.pow(1024, 3) / 100.00; 140 | String finalstring = "4;" + "TIME:;" + timestamp + ';' 141 | + "CPU:;" + cpu + "%;" 142 | + "MEM:;" + memory + ';' 143 | + "Proc:;" + threads; 144 | System.out.println(finalstring); 145 | output.print(finalstring); 146 | output.flush(); 147 | // output.close(); 148 | try { 149 | Thread.sleep(1000); 150 | } catch (Exception e) { 151 | e.printStackTrace(); 152 | } 153 | } 154 | } 155 | }; 156 | thread.setPriority(Thread.MAX_PRIORITY); 157 | thread.start(); 158 | } 159 | } else { 160 | trayIcon.setToolTip("Disconnected"); 161 | chosenPort.closePort(); 162 | chosenPort = null; 163 | portList.setEnabled(true); 164 | connectButton.setText("Select"); 165 | } 166 | } 167 | }); 168 | 169 | window.addWindowListener(new WindowAdapter() { 170 | 171 | @Override 172 | public void windowClosing(WindowEvent e) { 173 | window.setVisible(false); 174 | window.dispose(); 175 | window = null; 176 | } 177 | }); 178 | window.setVisible(true); 179 | } 180 | 181 | private static void createAndShowGUI() { 182 | if (!SystemTray.isSupported()) { 183 | System.out.println("SystemTray is not supported"); 184 | return; 185 | } 186 | final PopupMenu popup = new PopupMenu(); 187 | trayIcon = new TrayIcon(createImage("/img/arduino.png", "tray icon")); 188 | final SystemTray tray = SystemTray.getSystemTray(); 189 | 190 | MenuItem aboutItem = new MenuItem("About"); 191 | MenuItem selectItem = new MenuItem("Select ComPort"); 192 | MenuItem exitItem = new MenuItem("Exit"); 193 | 194 | popup.add(aboutItem); 195 | popup.addSeparator(); 196 | popup.add(selectItem); 197 | popup.addSeparator(); 198 | popup.add(exitItem); 199 | 200 | trayIcon.setPopupMenu(popup); 201 | trayIcon.setToolTip("Disconnected"); 202 | 203 | try { 204 | tray.add(trayIcon); 205 | } catch (AWTException e) { 206 | System.out.println("TrayIcon could not be added."); 207 | return; 208 | } 209 | 210 | trayIcon.addActionListener(new ActionListener() { 211 | public void actionPerformed(ActionEvent e) { 212 | select_comport(); 213 | } 214 | }); 215 | 216 | aboutItem.addActionListener(new ActionListener() { 217 | public void actionPerformed(ActionEvent e) { 218 | JLabel label = new JLabel(); 219 | Font font = label.getFont(); 220 | StringBuffer style = new StringBuffer("font-family:" + font.getFamily() + ";"); 221 | style.append("font-weight:" + (font.isBold() ? "bold" : "normal") + ";"); 222 | style.append("font-size:" + font.getSize() + "pt;"); 223 | JEditorPane ep = new JEditorPane("text/html", "" 224 | + "Developed by Tekks
" + "Licensed under the Apache License, Version 2.0
" 225 | + "visit Tekks.de for more Information" 226 | + ""); 227 | HyperlinkListener hyperlinkListener = new ExtHyperLinkListener(ep); 228 | ep.addHyperlinkListener(hyperlinkListener); 229 | ep.setEditable(false); 230 | ep.setBackground(label.getBackground()); 231 | JOptionPane.showMessageDialog(null, ep, "Arduino Interface | About", JOptionPane.INFORMATION_MESSAGE, 232 | null); 233 | } 234 | }); 235 | 236 | selectItem.addActionListener(new ActionListener() { 237 | public void actionPerformed(ActionEvent e) { 238 | select_comport(); 239 | } 240 | }); 241 | 242 | exitItem.addActionListener(new ActionListener() { 243 | public void actionPerformed(ActionEvent e) { 244 | tray.remove(trayIcon); 245 | System.exit(0); 246 | } 247 | }); 248 | } 249 | 250 | protected static Image createImage(String path, String description) { 251 | URL imageURL = Arduino_Interface.class.getResource(path); 252 | 253 | if (imageURL == null) { 254 | System.err.println("Resource not found: " + path); 255 | return null; 256 | } else { 257 | return (new ImageIcon(imageURL, description)).getImage(); 258 | } 259 | } 260 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Arduino_libraries/HX8347_kbv.cpp: -------------------------------------------------------------------------------- 1 | #if defined(AVR) 2 | #include "HX8347_kbv.h" 3 | 4 | #if USE_MBED 5 | #define CS_IDLE { _lcd_pin_cs = 1; } 6 | #define CS_ACTIVE _lcd_pin_cs = 0 7 | #define CD_DATA { _lcd_pin_rs = 1; } 8 | #define CD_COMMAND _lcd_pin_rs = 0 9 | #define RESET_IDLE _lcd_pin_reset = 1 10 | #define RESET_ACTIVE _lcd_pin_reset = 0 11 | #define xchg8(x) _spi.write((uint8_t)x) 12 | #define write8(x) { _spi.write((uint8_t)x); } 13 | #define write16(x) { uint8_t h = (x)>>8, l = x; write8(h); write8(l); } 14 | #define WriteCmd(x) { CD_COMMAND; write8(x); } 15 | #define WriteData(x) { CD_DATA; write8(x); } 16 | 17 | HX8347_kbv::HX8347_kbv(PinName CS, PinName RS, PinName RST) 18 | : _lcd_pin_rs(RS), _lcd_pin_cs(CS), _lcd_pin_reset(RST), _spi(D11, D12, D13), Adafruit_GFX(240, 320) 19 | { 20 | _spi.format(8, 0); 21 | _spi.frequency(12000000); 22 | CS_IDLE; 23 | RESET_IDLE; 24 | } 25 | #else 26 | #if 1 27 | #include 28 | #if 0 29 | #elif defined(__AVR_ATmega328P__) 30 | #define CD_PORT PORTD 31 | #define CD_PIN PD7 //digital#7 32 | #define CS_PORT PORTB 33 | #define CS_PIN PB2 //digital#10 34 | #define RESET_PORT PORTB 35 | #define RESET_PIN PB1 //Backlight //digital#9 36 | #define SD_PORT PORTD 37 | #define SD_PIN PD5 //digital#5 38 | #define XPT_PORT PORTD 39 | #define XPT_PIN PD4 //digital#4 40 | #define SPI_SS PB2 41 | #define SPI_SCK PB5 42 | #define SPI_MOSI PB3 43 | #elif defined(__AVR_ATmega32U4__) 44 | #define CD_PORT PORTE 45 | #define CD_PIN PE6 //digital#7 46 | #define CS_PORT PORTB 47 | #define CS_PIN PB6 //digital#10 48 | #define RESET_PORT PORTB 49 | #define RESET_PIN PB5 //Backlight //digital#9 50 | #define SD_PORT PORTC 51 | #define SD_PIN PC6 //digital#5 52 | #define XPT_PORT PORTD 53 | #define XPT_PIN PD4 //digital#4 54 | #define SPI_SS PB0 55 | #define SPI_SCK PB1 56 | #define SPI_MOSI PB2 57 | #elif defined(__AVR_ATmega2560__) 58 | #define CD_PORT PORTH 59 | #define CD_PIN PH4 //digital#7 60 | #define CS_PORT PORTB 61 | #define CS_PIN PB4 //digital#10 62 | #define RESET_PORT PORTH 63 | #define RESET_PIN PH6 //Backlight //digital#9 64 | #define SD_PORT PORTE 65 | #define SD_PIN PE3 //digital#5 66 | #define XPT_PORT PORTG 67 | #define XPT_PIN PG5 //digital#4 68 | #define SPI_SS PB0 69 | #define SPI_SCK PB1 70 | #define SPI_MOSI PB2 71 | #else 72 | #error 73 | #endif 74 | 75 | #define SETDDR { CS_OUTPUT; RESET_OUTPUT; CD_OUTPUT; SD_OUTPUT; XPT_OUTPUT; } 76 | #define INIT() { CS_IDLE; RESET_IDLE; SD_IDLE; XPT_IDLE; SETDDR; spi_init(); } 77 | 78 | #define SPCRVAL ((1<>8, l = x; write8(h); write8(l); } 137 | #define WriteCmd(x) { flush(); CD_COMMAND; write8(x); flush(); } 138 | #define WriteData(x) { CD_DATA; write16(x); } 139 | 140 | #define wait_ms(ms) delay(ms) 141 | 142 | HX8347_kbv::HX8347_kbv():Adafruit_GFX(240, 320) 143 | { 144 | INIT(); 145 | CS_IDLE; 146 | RESET_IDLE; 147 | } 148 | #endif 149 | 150 | void HX8347_kbv::reset(void) 151 | { 152 | wait_ms(50); 153 | RESET_ACTIVE; 154 | wait_ms(100); 155 | RESET_IDLE; 156 | wait_ms(100); 157 | } 158 | 159 | void HX8347_kbv::WriteCmdData(uint16_t cmd, uint16_t dat) 160 | { 161 | CS_ACTIVE; 162 | WriteCmd(cmd); 163 | WriteData(dat); 164 | CS_IDLE; 165 | } 166 | 167 | #define WriteCmdDataPair(c, d) { WriteCmdData(c, (d)>>8); WriteCmdData(c+1, (d)&0xFF); } 168 | #define HX8347G_COLADDRSTART_HI 0x02 169 | #define HX8347G_COLADDRSTART_LO 0x03 170 | #define HX8347G_COLADDREND_HI 0x04 171 | #define HX8347G_COLADDREND_LO 0x05 172 | #define HX8347G_ROWADDRSTART_HI 0x06 173 | #define HX8347G_ROWADDRSTART_LO 0x07 174 | #define HX8347G_ROWADDREND_HI 0x08 175 | #define HX8347G_ROWADDREND_LO 0x09 176 | #define HX8347G_MEMACCESS 0x16 177 | #define HX8347G_MEMWRITE 0x22 178 | #define HX8347G_MEMREAD 0x22 179 | 180 | uint16_t HX8347_kbv::readReg(uint16_t reg) 181 | { 182 | uint8_t h, l; 183 | CS_ACTIVE; 184 | WriteCmd(reg); 185 | CD_DATA; //should do a flush() 186 | 187 | // h = xchg8(0xFF); 188 | l = xchg8(0xFF); 189 | CS_IDLE; 190 | return (h << 8) | l; 191 | } 192 | 193 | int16_t HX8347_kbv::readGRAM(int16_t x, int16_t y, uint16_t * block, int16_t w, int16_t h) 194 | { 195 | return -1; // .kbv HX8347-D has IM=0110. HX8347-G is r/w IM=1110 (4-wire Serial II) 196 | /* 197 | uint8_t r, g, b; 198 | int16_t n = w * h; // we are NEVER going to read > 32k pixels at once 199 | 200 | setAddrWindow(x, y, x + n - 1, y + h - 1); 201 | CS_ACTIVE; 202 | WriteCmd(HX8347G_MEMREAD); 203 | CD_DATA; 204 | 205 | r = xchg8(0xFF); // needs 2 dummy read 206 | g = xchg8(0xFF); // needs 2 dummy read 207 | while (n-- > 0) { 208 | r = xchg8(0xFF); 209 | g = xchg8(0xFF); 210 | *block++ = (r << 8u)|(g); 211 | } 212 | CS_IDLE; 213 | return 0; 214 | */ 215 | } 216 | 217 | void HX8347_kbv::setRotation(uint8_t r) 218 | { 219 | uint16_t mac = 0x0800; 220 | Adafruit_GFX::setRotation(r & 3); 221 | switch (rotation) { 222 | case 0: 223 | mac = 0x0800; // BGR=1 224 | break; 225 | case 1: 226 | mac = 0x6800; //MY=0, MX=1, MV=0, ML=0, BGR=1 227 | break; 228 | case 2: 229 | mac = 0xD800; //MY=1, MX=1, MV=0, ML=1, BGR=1 230 | break; 231 | case 3: 232 | mac = 0xB800; //MY=1, MX=0, MV=1, ML=1, BGR=1 233 | break; 234 | } 235 | WriteCmdData(HX8347G_MEMACCESS, mac >> 8); 236 | } 237 | 238 | void HX8347_kbv::drawPixel(int16_t x, int16_t y, uint16_t color) 239 | { 240 | // ILI934X just plots at edge if you try to write outside of the box: 241 | if (x < 0 || y < 0 || x >= width() || y >= height()) return; 242 | WriteCmdDataPair(HX8347G_COLADDRSTART_HI, x); 243 | WriteCmdDataPair(HX8347G_COLADDREND_HI, x); 244 | WriteCmdDataPair(HX8347G_ROWADDRSTART_HI, y); 245 | WriteCmdDataPair(HX8347G_ROWADDREND_HI, y); 246 | CS_ACTIVE; 247 | WriteCmd(HX8347G_MEMWRITE); 248 | CD_DATA; 249 | write16(color); 250 | CS_IDLE; 251 | } 252 | 253 | void HX8347_kbv::setAddrWindow(int16_t x, int16_t y, int16_t x1, int16_t y1) 254 | { 255 | CS_ACTIVE; 256 | WriteCmdDataPair(HX8347G_COLADDRSTART_HI, x); 257 | WriteCmdDataPair(HX8347G_COLADDREND_HI, x1); 258 | WriteCmdDataPair(HX8347G_ROWADDRSTART_HI, y); 259 | WriteCmdDataPair(HX8347G_ROWADDREND_HI, y1); 260 | CS_IDLE; 261 | } 262 | 263 | void HX8347_kbv::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) 264 | { 265 | int16_t end; 266 | if (w < 0) { w = -w; x -= w; } //+ve w 267 | end = x + w; 268 | if (x < 0) x = 0; 269 | if (end > width()) end = width(); 270 | w = end - x; 271 | if (h < 0) { h = -h; y -= h; } //+ve h 272 | end = y + h; 273 | if (y < 0) y = 0; 274 | if (end > height()) end = height(); 275 | h = end - y; 276 | setAddrWindow(x, y, x+w-1, y+h-1); 277 | CS_ACTIVE; 278 | WriteCmd(HX8347G_MEMWRITE); 279 | CD_DATA; 280 | if (h > w) { end = h; h = w; w = end; } 281 | uint8_t hi = color >> 8; 282 | uint8_t lo = color; 283 | while (h-- > 0) { 284 | for (int16_t i = w; i-- > 0; ) { 285 | write8(hi); 286 | asm("nop"); 287 | asm("nop"); 288 | asm("nop"); 289 | write8(lo); 290 | // asm("nop"); 291 | // asm("nop"); 292 | } 293 | } 294 | CS_IDLE; 295 | // setAddrWindow(0, 0, width()-1, height()-1); 296 | } 297 | 298 | void HX8347_kbv::pushColors(uint16_t * block, int16_t n, bool first) 299 | { 300 | uint16_t color; 301 | CS_ACTIVE; 302 | if (first) { 303 | WriteCmd(HX8347G_MEMWRITE); 304 | } 305 | CD_DATA; 306 | while (n-- > 0) { 307 | color = *block++; 308 | write16(color); 309 | } 310 | CS_IDLE; 311 | } 312 | 313 | void HX8347_kbv::pushColors(uint8_t * block, int16_t n, bool first) 314 | { 315 | uint16_t color; 316 | uint8_t h, l; 317 | CS_ACTIVE; 318 | if (first) { 319 | WriteCmd(HX8347G_MEMWRITE); 320 | } 321 | CD_DATA; 322 | while (n-- > 0) { 323 | h = (*block++); 324 | l = (*block++); 325 | color = (h << 8) | l; 326 | write16(color); 327 | } 328 | CS_IDLE; 329 | } 330 | 331 | void HX8347_kbv::pushColors(const uint8_t * block, int16_t n, bool first, bool bigend) 332 | { 333 | uint16_t color; 334 | uint8_t h, l; 335 | CS_ACTIVE; 336 | if (first) { 337 | WriteCmd(HX8347G_MEMWRITE); 338 | } 339 | CD_DATA; 340 | while (n-- > 0) { 341 | l = pgm_read_byte(block++); 342 | h = pgm_read_byte(block++); 343 | color = (bigend) ? (l << 8 ) | h : (h << 8) | l; 344 | write16(color); 345 | } 346 | CS_IDLE; 347 | } 348 | 349 | void HX8347_kbv::invertDisplay(bool i) 350 | { 351 | uint8_t val = 0x00; 352 | // val = readReg(0x36); //.kbv HX8347-D can't read SPI. 353 | if (i) val |= 2; 354 | else val &= ~2; 355 | WriteCmdData(0x36, val); 356 | } 357 | 358 | void HX8347_kbv::vertScroll(int16_t top, int16_t scrollines, int16_t offset) 359 | { 360 | int16_t bfa = HEIGHT - top - scrollines; // bottom fixed area 361 | int16_t vsp; 362 | if (offset <= -scrollines || offset >= scrollines) offset = 0; //valid scroll 363 | vsp = top + offset; // vertical start position 364 | if (offset < 0) 365 | vsp += scrollines; //keep in unsigned range 366 | WriteCmdData(0x01, 8); //VLE 367 | WriteCmdDataPair(0x0E, top); //TOP 368 | WriteCmdDataPair(0x10, scrollines); 369 | WriteCmdDataPair(0x12, 320 - top - scrollines); 370 | WriteCmdDataPair(0x14, vsp); //VL# 371 | 372 | } 373 | 374 | #define TFTLCD_DELAY 0xFF 375 | 376 | static const uint8_t HX8347G_regValues[] PROGMEM = { 377 | 0x2E , 0x89, 378 | 0x29 , 0x8F, 379 | 0x2B , 0x02, 380 | 0xE2 , 0x00, 381 | 0xE4 , 0x01, 382 | 0xE5 , 0x10, 383 | 0xE6 , 0x01, 384 | 0xE7 , 0x10, 385 | 0xE8 , 0x70, 386 | 0xF2 , 0x00, 387 | 0xEA , 0x00, 388 | 0xEB , 0x20, 389 | 0xEC , 0x3C, 390 | 0xED , 0xC8, 391 | 0xE9 , 0x38, 392 | 0xF1 , 0x01, 393 | 394 | // skip gamma, do later 395 | 396 | 0x1B , 0x1A, 397 | 0x1A , 0x02, 398 | 0x24 , 0x61, 399 | 0x25 , 0x5C, 400 | 401 | 0x18 , 0x36, 402 | 0x19 , 0x01, 403 | 0x1F , 0x88, 404 | TFTLCD_DELAY , 5 , // delay 5 ms 405 | 0x1F , 0x80, 406 | TFTLCD_DELAY , 5 , 407 | 0x1F , 0x90, 408 | TFTLCD_DELAY , 5 , 409 | 0x1F , 0xD4, 410 | TFTLCD_DELAY , 5 , 411 | 0x17 , 0x05, 412 | 413 | 0x36 , 0x00, // .kbv was 0x09 414 | 0x28 , 0x38, 415 | TFTLCD_DELAY , 40 , 416 | 0x28 , 0x3C, 417 | 418 | 0x02 , 0x00, 419 | 0x03 , 0x00, 420 | 0x04 , 0x00, 421 | 0x05 , 0xEF, 422 | 0x06 , 0x00, 423 | 0x07 , 0x00, 424 | 0x08 , 0x01, 425 | 0x09 , 0x3F 426 | }; 427 | static const uint8_t HX8347G_2_regValues[] PROGMEM = { 428 | 0xEA,0x00, //PTBA[15:8] 429 | 0xEB,0x20, //PTBA[7:0] 430 | 0xEC,0x0C, //STBA[15:8] 431 | 0xED,0xC4, //STBA[7:0] 432 | 0xE8,0x38, //OPON[7:0] 433 | 0xE9,0x10, //OPON1[7:0] 434 | 0xF1,0x01, //OTPS1B 435 | 0xF2,0x10, //GEN 436 | //Gamma 2.2 Setting 437 | 0x40,0x01, // 438 | 0x41,0x00, // 439 | 0x42,0x00, // 440 | 0x43,0x10, // 441 | 0x44,0x0E, // 442 | 0x45,0x24, // 443 | 0x46,0x04, // 444 | 0x47,0x50, // 445 | 0x48,0x02, // 446 | 0x49,0x13, // 447 | 0x4A,0x19, // 448 | 0x4B,0x19, // 449 | 0x4C,0x16, // 450 | 0x50,0x1B, // 451 | 0x51,0x31, // 452 | 0x52,0x2F, // 453 | 0x53,0x3F, // 454 | 0x54,0x3F, // 455 | 0x55,0x3E, // 456 | 0x56,0x2F, // 457 | 0x57,0x7B, // 458 | 0x58,0x09, // 459 | 0x59,0x06, // 460 | 0x5A,0x06, // 461 | 0x5B,0x0C, // 462 | 0x5C,0x1D, // 463 | 0x5D,0xCC, // 464 | //Power Voltage Setting 465 | 0x1B,0x1B, //VRH=4.65V 466 | 0x1A,0x01, //BT (VGH~15V,VGL~-10V,DDVDH~5V) 467 | 0x24,0x2F, //VMH(VCOM High voltage ~3.2V) 468 | 0x25,0x57, //VML(VCOM Low voltage -1.2V) 469 | //****VCOM offset**/// 470 | 0x23,0x88, //for Flicker adjust //can reload from OTP 471 | //Power on Setting 472 | 0x18,0x34, //I/P_RADJ,N/P_RADJ, Normal mode 60Hz 473 | 0x19,0x01, //OSC_EN='1', start Osc 474 | 0x01,0x00, //DP_STB='0', out deep sleep 475 | 0x1F,0x88,// GAS=1, VOMG=00, PON=0, DK=1, XDK=0, DVDH_TRI=0, STB=0 476 | TFTLCD_DELAY, 5, 477 | 0x1F,0x80,// GAS=1, VOMG=00, PON=0, DK=0, XDK=0, DVDH_TRI=0, STB=0 478 | TFTLCD_DELAY, 5, 479 | 0x1F,0x90,// GAS=1, VOMG=00, PON=1, DK=0, XDK=0, DVDH_TRI=0, STB=0 480 | TFTLCD_DELAY, 5, 481 | 0x1F,0xD0,// GAS=1, VOMG=10, PON=1, DK=0, XDK=0, DDVDH_TRI=0, STB=0 482 | TFTLCD_DELAY, 5, 483 | //262k/65k color selection 484 | 0x17,0x05, //default 0x06 262k color // 0x05 65k color 485 | //SET PANEL 486 | 0x36,0x00, //SS_P, GS_P,REV_P,BGR_P 487 | //Display ON Setting 488 | 0x28,0x38, //GON=1, DTE=1, D=1000 489 | TFTLCD_DELAY, 40, 490 | 0x28,0x3F, //GON=1, DTE=1, D=1100 491 | 492 | 0x16,0x18, 493 | //Set GRAM Area 494 | 0x02,0x00, 495 | 0x03,0x00, //Column Start 496 | 0x04,0x00, 497 | 0x05,0xEF, //Column End 498 | 0x06,0x00, 499 | 0x07,0x00, //Row Start 500 | 0x08,0x01, 501 | 0x09,0x3F, //Row End 502 | }; 503 | 504 | void HX8347_kbv::begin(uint16_t ID) 505 | { 506 | _lcd_ID = ID; 507 | uint8_t cmd, d; 508 | uint8_t *p = (uint8_t *) HX8347G_2_regValues; 509 | int16_t size = sizeof(HX8347G_2_regValues); 510 | reset(); 511 | while (size > 0) { 512 | cmd = pgm_read_byte(p++); 513 | d = pgm_read_byte(p++); 514 | size -= 2; 515 | if (cmd == TFTLCD_DELAY) wait_ms(d); 516 | else WriteCmdData(cmd, d); 517 | } 518 | setRotation(0); //PORTRAIT 519 | } 520 | #endif 521 | --------------------------------------------------------------------------------