diff --git a/SmartyKit 1 basic drivers/SmartyKit1_KeyboardDriverBasic/SmartyKit1_KeyboardDriverBasic.ino b/SmartyKit 1 basic drivers/SmartyKit1_KeyboardDriverBasic/SmartyKit1_KeyboardDriverBasic.ino new file mode 100644 index 0000000..7b24273 --- /dev/null +++ b/SmartyKit 1 basic drivers/SmartyKit1_KeyboardDriverBasic/SmartyKit1_KeyboardDriverBasic.ino @@ -0,0 +1,167 @@ + /* SmartyKit 1 - PS/2 keyboard driver + * http://www.smartykit.io/ + * Copyright (C) 2020, Sergey Panarin + * + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "PS2Keyboard.h" + +// Keyboard Driver pins connections: +// D0 & D1 – reserved for Serial connection +// D2 –> PS/2 Socket Data pin +// D3 -> 4-16 ports decoder Kbd (2) out pin (signal is active when CPU reads Keyboatrd port) +// D4 -> PS/2 Socket Clk pin +// D5 -> Keyboard BIT7 pin output +// D6-D13 -> Keyboard data bus output (8 pins) to connect to Keyboard port (char code is transfered here) +// A4 -> Low-rate clock output for CPU CLK input +// A5 -> Low-rate clock output for indicating LED connection + +const int PS2Socket_Data = 2; +const int CPUreadsKeyboardPin = 3; +const int PS2Socket_Clk = 4; + + +const int KeyboardBIT7pin = 5; // +const int DataBus[8] = {6, 7, 8, 9, 10, 11, 12, 13}; +static boolean BIT7flag = false; + +//low-rate clock for tests on A4-A5 +#define CLOCK A4 +#define LED A5 +int lowRateClockPeriod = 10; //10 milliseconds = 100 times per second (100 Hz) + +//#define _WITH_SERIAL_ +#define _WITH_PS2_ + +#ifdef _WITH_PS2_ +PS2Keyboard keyboard; +#endif + +void setup() +{ + pinMode(CLOCK, OUTPUT); + pinMode(LED, OUTPUT); + + pinMode(CPUreadsKeyboardPin, INPUT_PULLUP); + + for (int count = 1; count <= 8; count++) { + pinMode(DataBus[count-1], OUTPUT); + }; + pinMode(KeyboardBIT7pin, OUTPUT); + KeyboardBIT7_Disable(); + + delay(500); //7500 for debug without Keyboard connected + +#ifdef _WITH_PS2_ + keyboard.begin(PS2Socket_Clk, PS2Socket_Data); +#endif + attachInterrupt(1, cpuReadsKeyboard, FALLING); + +#ifdef _WITH_SERIAL_ + Serial.begin(9600); + Serial.println("SmartyKit 1 Serial Keyboard is ready..."); + #endif +} + +void cpuReadsKeyboard(void) +{ + KeyboardBIT7_Disable(); +} + +void KeyboardBIT7_Enable() +{ + digitalWrite(KeyboardBIT7pin, HIGH); + BIT7flag = true; +} +void KeyboardBIT7_Disable() +{ + digitalWrite(KeyboardBIT7pin, LOW); + BIT7flag = false; +} + +void sendCharToKeyboardPort(char c) +{ + while(BIT7flag == true) //wait untill the previous char is read by CPU + delay(5); + + for (int count = 1; count <= 8 ; count++) + { + if (c & (1 << (count-1))) + digitalWrite(DataBus[count-1], HIGH); + else + digitalWrite(DataBus[count-1], LOW); + } + digitalWrite(DataBus[7], HIGH); + KeyboardBIT7_Enable(); +} + +void loop() { + + +#ifdef _WITH_PS2_ + //check PS2 input + if (keyboard.available()) { + char c = keyboard.read(); + + if (c == PS2_TAB) + preLoadTest(); + + //process Backspace, Left Arrow, Delete as Apple I backspace '_' + if (c == PS2_BACKSPACE) { + c = '_'; + } else if (c == PS2_LEFTARROW) { + c = '_'; + } else if (c == PS2_DELETE) { + c = '_'; + } + + int scan_code = (int)c; + //make all symbols uppercase + if (scan_code >= 0x60) + scan_code -= 0x20; + c = (char) scan_code; + //print c to Keyboard Port to be read by CPU + sendCharToKeyboardPort(c); + #ifdef _WITH_SERIAL_ + Serial.print(c); + if (c == '\r') + Serial.println(); + #endif + } +#endif + + //low-rate clock + digitalWrite(CLOCK, HIGH); + digitalWrite(LED, HIGH); + delay(lowRateClockPeriod); // wait for a lowRateClockPeriod + digitalWrite(CLOCK, LOW); + digitalWrite(LED, LOW); + delay(lowRateClockPeriod); // wait for a lowRateClockPeriod +} + +void preLoadTest() +{ + const int CMD_COUNT = 4; + String cmd1 = String("1111: 88 A8 50\r"); + String cmd2 = String(":07 61 92\r"); + String cmd3 = String(":94 67\r"); + String cmd4 = String("FC00R\r"); + String commands[] = {cmd1, cmd2, cmd3, cmd4}; + for (int i = 0; i < CMD_COUNT; i++) + for (int j = 0; j < commands[i].length(); j++) + { + char c = commands[i].charAt(j); + sendCharToKeyboardPort(c); + } + +} diff --git a/SmartyKit 1 basic drivers/SmartyKit1_VideoDriverBasic_TFT2.8_TV/SmartyKit1_VideoDriverBasic_TFT2.8_TV.ino b/SmartyKit 1 basic drivers/SmartyKit1_VideoDriverBasic_TFT2.8_TV/SmartyKit1_VideoDriverBasic_TFT2.8_TV.ino new file mode 100644 index 0000000..97fca0b --- /dev/null +++ b/SmartyKit 1 basic drivers/SmartyKit1_VideoDriverBasic_TFT2.8_TV/SmartyKit1_VideoDriverBasic_TFT2.8_TV.ino @@ -0,0 +1,1562 @@ +/* SmartyKit 1 - 2.8" TFT 320x240 screen video driver (+TV) + * http://www.smartykit.io/ + * Copyright (C) 2019, Sergey Panarin + * + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#define _SMARTYKIT_DISPLAY_DRIVER_IL9341H_ +#define _SMARTY_DEBUG_ + +#include + + +#include +#undef _TERMINAL_ //turn off Terminal +//#define _TERMINAL_ //turn on Terminal + +#ifdef _TERMINAL_ +// Create a terminal in TWI mode +Terminal term; //uses A4 (SDA) and A5 (SCL) that conflict with other usage of A4-A5 + //so we need to put CS on low, RST = A0, DC = A1, MOSI = A2, SCK = A3, MISO = not connected (NC) +#endif + + +// Video Driver pins connections: +// D0 & D1 – reserved for Serial connection +// D2 -> NC +// D3 –> 4-16 ports decoder Video (9) out pin (signal is active when CPU writes to Video port) +// D4 -> NC +// D5 -> Video BIT7 pin output +// D6-D13 -> Video data bus input (8 pins) to connect to Video port (char code is transfered here) +// A0-A3 -> 2.8" TFT 320x240 screen connection +// A4-A5 -> TV terminal via I2C (TWI) + +// Standard ASCII 5x7 font + +static const unsigned char font[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, 0x3E, 0x6B, + 0x4F, 0x6B, 0x3E, 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, 0x18, 0x3C, 0x7E, 0x3C, + 0x18, 0x1C, 0x57, 0x7D, 0x57, 0x1C, 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, 0x00, + 0x18, 0x3C, 0x18, 0x00, 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, 0x00, 0x18, 0x24, + 0x18, 0x00, 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, 0x30, 0x48, 0x3A, 0x06, 0x0E, + 0x26, 0x29, 0x79, 0x29, 0x26, 0x40, 0x7F, 0x05, 0x05, 0x07, 0x40, 0x7F, + 0x05, 0x25, 0x3F, 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, 0x7F, 0x3E, 0x1C, 0x1C, + 0x08, 0x08, 0x1C, 0x1C, 0x3E, 0x7F, 0x14, 0x22, 0x7F, 0x22, 0x14, 0x5F, + 0x5F, 0x00, 0x5F, 0x5F, 0x06, 0x09, 0x7F, 0x01, 0x7F, 0x00, 0x66, 0x89, + 0x95, 0x6A, 0x60, 0x60, 0x60, 0x60, 0x60, 0x94, 0xA2, 0xFF, 0xA2, 0x94, + 0x08, 0x04, 0x7E, 0x04, 0x08, 0x10, 0x20, 0x7E, 0x20, 0x10, 0x08, 0x08, + 0x2A, 0x1C, 0x08, 0x08, 0x1C, 0x2A, 0x08, 0x08, 0x1E, 0x10, 0x10, 0x10, + 0x10, 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, 0x30, 0x38, 0x3E, 0x38, 0x30, 0x06, + 0x0E, 0x3E, 0x0E, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, + 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x14, 0x7F, 0x14, 0x7F, 0x14, + 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x23, 0x13, 0x08, 0x64, 0x62, 0x36, 0x49, + 0x56, 0x20, 0x50, 0x00, 0x08, 0x07, 0x03, 0x00, 0x00, 0x1C, 0x22, 0x41, + 0x00, 0x00, 0x41, 0x22, 0x1C, 0x00, 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 0x08, + 0x08, 0x3E, 0x08, 0x08, 0x00, 0x80, 0x70, 0x30, 0x00, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x00, 0x00, 0x60, 0x60, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, + 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, 0x42, 0x7F, 0x40, 0x00, 0x72, 0x49, + 0x49, 0x49, 0x46, 0x21, 0x41, 0x49, 0x4D, 0x33, 0x18, 0x14, 0x12, 0x7F, + 0x10, 0x27, 0x45, 0x45, 0x45, 0x39, 0x3C, 0x4A, 0x49, 0x49, 0x31, 0x41, + 0x21, 0x11, 0x09, 0x07, 0x36, 0x49, 0x49, 0x49, 0x36, 0x46, 0x49, 0x49, + 0x29, 0x1E, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x40, 0x34, 0x00, 0x00, + 0x00, 0x08, 0x14, 0x22, 0x41, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x41, + 0x22, 0x14, 0x08, 0x02, 0x01, 0x59, 0x09, 0x06, 0x3E, 0x41, 0x5D, 0x59, + 0x4E, 0x7C, 0x12, 0x11, 0x12, 0x7C, 0x7F, 0x49, 0x49, 0x49, 0x36, 0x3E, + 0x41, 0x41, 0x41, 0x22, 0x7F, 0x41, 0x41, 0x41, 0x3E, 0x7F, 0x49, 0x49, + 0x49, 0x41, 0x7F, 0x09, 0x09, 0x09, 0x01, 0x3E, 0x41, 0x41, 0x51, 0x73, + 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00, 0x41, 0x7F, 0x41, 0x00, 0x20, 0x40, + 0x41, 0x3F, 0x01, 0x7F, 0x08, 0x14, 0x22, 0x41, 0x7F, 0x40, 0x40, 0x40, + 0x40, 0x7F, 0x02, 0x1C, 0x02, 0x7F, 0x7F, 0x04, 0x08, 0x10, 0x7F, 0x3E, + 0x41, 0x41, 0x41, 0x3E, 0x7F, 0x09, 0x09, 0x09, 0x06, 0x3E, 0x41, 0x51, + 0x21, 0x5E, 0x7F, 0x09, 0x19, 0x29, 0x46, 0x26, 0x49, 0x49, 0x49, 0x32, + 0x03, 0x01, 0x7F, 0x01, 0x03, 0x3F, 0x40, 0x40, 0x40, 0x3F, 0x1F, 0x20, + 0x40, 0x20, 0x1F, 0x3F, 0x40, 0x38, 0x40, 0x3F, 0x63, 0x14, 0x08, 0x14, + 0x63, 0x03, 0x04, 0x78, 0x04, 0x03, 0x61, 0x59, 0x49, 0x4D, 0x43, 0x00, + 0x7F, 0x41, 0x41, 0x41, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x41, 0x41, + 0x41, 0x7F, 0x04, 0x02, 0x01, 0x02, 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, + 0x00, 0x03, 0x07, 0x08, 0x00, 0x20, 0x54, 0x54, 0x78, 0x40, 0x7F, 0x28, + 0x44, 0x44, 0x38, 0x38, 0x44, 0x44, 0x44, 0x28, 0x38, 0x44, 0x44, 0x28, + 0x7F, 0x38, 0x54, 0x54, 0x54, 0x18, 0x00, 0x08, 0x7E, 0x09, 0x02, 0x18, + 0xA4, 0xA4, 0x9C, 0x78, 0x7F, 0x08, 0x04, 0x04, 0x78, 0x00, 0x44, 0x7D, + 0x40, 0x00, 0x20, 0x40, 0x40, 0x3D, 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, + 0x00, 0x41, 0x7F, 0x40, 0x00, 0x7C, 0x04, 0x78, 0x04, 0x78, 0x7C, 0x08, + 0x04, 0x04, 0x78, 0x38, 0x44, 0x44, 0x44, 0x38, 0xFC, 0x18, 0x24, 0x24, + 0x18, 0x18, 0x24, 0x24, 0x18, 0xFC, 0x7C, 0x08, 0x04, 0x04, 0x08, 0x48, + 0x54, 0x54, 0x54, 0x24, 0x04, 0x04, 0x3F, 0x44, 0x24, 0x3C, 0x40, 0x40, + 0x20, 0x7C, 0x1C, 0x20, 0x40, 0x20, 0x1C, 0x3C, 0x40, 0x30, 0x40, 0x3C, + 0x44, 0x28, 0x10, 0x28, 0x44, 0x4C, 0x90, 0x90, 0x90, 0x7C, 0x44, 0x64, + 0x54, 0x4C, 0x44, 0x00, 0x08, 0x36, 0x41, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x41, 0x36, 0x08, 0x00, 0x02, 0x01, 0x02, 0x04, 0x02, 0x3C, + 0x26, 0x23, 0x26, 0x3C, 0x1E, 0xA1, 0xA1, 0x61, 0x12, 0x3A, 0x40, 0x40, + 0x20, 0x7A, 0x38, 0x54, 0x54, 0x55, 0x59, 0x21, 0x55, 0x55, 0x79, 0x41, + 0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut + 0x21, 0x55, 0x54, 0x78, 0x40, 0x20, 0x54, 0x55, 0x79, 0x40, 0x0C, 0x1E, + 0x52, 0x72, 0x12, 0x39, 0x55, 0x55, 0x55, 0x59, 0x39, 0x54, 0x54, 0x54, + 0x59, 0x39, 0x55, 0x54, 0x54, 0x58, 0x00, 0x00, 0x45, 0x7C, 0x41, 0x00, + 0x02, 0x45, 0x7D, 0x42, 0x00, 0x01, 0x45, 0x7C, 0x40, 0x7D, 0x12, 0x11, + 0x12, 0x7D, // A-umlaut + 0xF0, 0x28, 0x25, 0x28, 0xF0, 0x7C, 0x54, 0x55, 0x45, 0x00, 0x20, 0x54, + 0x54, 0x7C, 0x54, 0x7C, 0x0A, 0x09, 0x7F, 0x49, 0x32, 0x49, 0x49, 0x49, + 0x32, 0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut + 0x32, 0x4A, 0x48, 0x48, 0x30, 0x3A, 0x41, 0x41, 0x21, 0x7A, 0x3A, 0x42, + 0x40, 0x20, 0x78, 0x00, 0x9D, 0xA0, 0xA0, 0x7D, 0x3D, 0x42, 0x42, 0x42, + 0x3D, // O-umlaut + 0x3D, 0x40, 0x40, 0x40, 0x3D, 0x3C, 0x24, 0xFF, 0x24, 0x24, 0x48, 0x7E, + 0x49, 0x43, 0x66, 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, 0xFF, 0x09, 0x29, 0xF6, + 0x20, 0xC0, 0x88, 0x7E, 0x09, 0x03, 0x20, 0x54, 0x54, 0x79, 0x41, 0x00, + 0x00, 0x44, 0x7D, 0x41, 0x30, 0x48, 0x48, 0x4A, 0x32, 0x38, 0x40, 0x40, + 0x22, 0x7A, 0x00, 0x7A, 0x0A, 0x0A, 0x72, 0x7D, 0x0D, 0x19, 0x31, 0x7D, + 0x26, 0x29, 0x29, 0x2F, 0x28, 0x26, 0x29, 0x29, 0x29, 0x26, 0x30, 0x48, + 0x4D, 0x40, 0x20, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x38, 0x2F, 0x10, 0xC8, 0xAC, 0xBA, 0x2F, 0x10, 0x28, 0x34, 0xFA, 0x00, + 0x00, 0x7B, 0x00, 0x00, 0x08, 0x14, 0x2A, 0x14, 0x22, 0x22, 0x14, 0x2A, + 0x14, 0x08, 0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old + // code + 0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block + 0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block + 0x00, 0x00, 0x00, 0xFF, 0x00, 0x10, 0x10, 0x10, 0xFF, 0x00, 0x14, 0x14, + 0x14, 0xFF, 0x00, 0x10, 0x10, 0xFF, 0x00, 0xFF, 0x10, 0x10, 0xF0, 0x10, + 0xF0, 0x14, 0x14, 0x14, 0xFC, 0x00, 0x14, 0x14, 0xF7, 0x00, 0xFF, 0x00, + 0x00, 0xFF, 0x00, 0xFF, 0x14, 0x14, 0xF4, 0x04, 0xFC, 0x14, 0x14, 0x17, + 0x10, 0x1F, 0x10, 0x10, 0x1F, 0x10, 0x1F, 0x14, 0x14, 0x14, 0x1F, 0x00, + 0x10, 0x10, 0x10, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x10, + 0x10, 0x1F, 0x10, 0x10, 0x10, 0x10, 0xF0, 0x10, 0x00, 0x00, 0x00, 0xFF, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xFF, 0x10, 0x00, + 0x00, 0x00, 0xFF, 0x14, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x1F, + 0x10, 0x17, 0x00, 0x00, 0xFC, 0x04, 0xF4, 0x14, 0x14, 0x17, 0x10, 0x17, + 0x14, 0x14, 0xF4, 0x04, 0xF4, 0x00, 0x00, 0xFF, 0x00, 0xF7, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0xF7, 0x00, 0xF7, 0x14, 0x14, 0x14, 0x17, + 0x14, 0x10, 0x10, 0x1F, 0x10, 0x1F, 0x14, 0x14, 0x14, 0xF4, 0x14, 0x10, + 0x10, 0xF0, 0x10, 0xF0, 0x00, 0x00, 0x1F, 0x10, 0x1F, 0x00, 0x00, 0x00, + 0x1F, 0x14, 0x00, 0x00, 0x00, 0xFC, 0x14, 0x00, 0x00, 0xF0, 0x10, 0xF0, + 0x10, 0x10, 0xFF, 0x10, 0xFF, 0x14, 0x14, 0x14, 0xFF, 0x14, 0x10, 0x10, + 0x10, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x38, 0x44, 0x44, + 0x38, 0x44, 0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta + 0x7E, 0x02, 0x02, 0x06, 0x06, 0x02, 0x7E, 0x02, 0x7E, 0x02, 0x63, 0x55, + 0x49, 0x41, 0x63, 0x38, 0x44, 0x44, 0x3C, 0x04, 0x40, 0x7E, 0x20, 0x1E, + 0x20, 0x06, 0x02, 0x7E, 0x02, 0x02, 0x99, 0xA5, 0xE7, 0xA5, 0x99, 0x1C, + 0x2A, 0x49, 0x2A, 0x1C, 0x4C, 0x72, 0x01, 0x72, 0x4C, 0x30, 0x4A, 0x4D, + 0x4D, 0x30, 0x30, 0x48, 0x78, 0x48, 0x30, 0xBC, 0x62, 0x5A, 0x46, 0x3D, + 0x3E, 0x49, 0x49, 0x49, 0x00, 0x7E, 0x01, 0x01, 0x01, 0x7E, 0x2A, 0x2A, + 0x2A, 0x2A, 0x2A, 0x44, 0x44, 0x5F, 0x44, 0x44, 0x40, 0x51, 0x4A, 0x44, + 0x40, 0x40, 0x44, 0x4A, 0x51, 0x40, 0x00, 0x00, 0xFF, 0x01, 0x03, 0xE0, + 0x80, 0xFF, 0x00, 0x00, 0x08, 0x08, 0x6B, 0x6B, 0x08, 0x36, 0x12, 0x36, + 0x24, 0x36, 0x06, 0x0F, 0x09, 0x0F, 0x06, 0x00, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x00, 0x10, 0x10, 0x00, 0x30, 0x40, 0xFF, 0x01, 0x01, 0x00, 0x1F, + 0x01, 0x01, 0x1E, 0x00, 0x19, 0x1D, 0x17, 0x12, 0x00, 0x3C, 0x3C, 0x3C, + 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00 // #255 NBSP +}; + +// allow clean compilation with [-Wunused-const-variable=] and [-Wall] +static inline void avoid_unused_const_variable_compiler_warning(void) { + (void)font; +} + + +#define BEEPER_PIN 6 + +//SmartyKit Display Driver parameters +#define ILI9341_TFTWIDTH 240 ///< ILI9341 max TFT width +#define ILI9341_TFTHEIGHT 320 ///< ILI9341 max TFT height + + +//driver commands and parameters +#define ILI9341_NOP 0x00 ///< No-op register +#define ILI9341_SWRESET 0x01 ///< Software reset register +#define ILI9341_RDDID 0x04 ///< Read display identification information +#define ILI9341_RDDST 0x09 ///< Read Display Status + +#define ILI9341_SLPIN 0x10 ///< Enter Sleep Mode +#define ILI9341_SLPOUT 0x11 ///< Sleep Out +#define ILI9341_PTLON 0x12 ///< Partial Mode ON +#define ILI9341_NORON 0x13 ///< Normal Display Mode ON + +#define ILI9341_RDMODE 0x0A ///< Read Display Power Mode +#define ILI9341_RDMADCTL 0x0B ///< Read Display MADCTL +#define ILI9341_RDPIXFMT 0x0C ///< Read Display Pixel Format +#define ILI9341_RDIMGFMT 0x0D ///< Read Display Image Format +#define ILI9341_RDSELFDIAG 0x0F ///< Read Display Self-Diagnostic Result + +#define ILI9341_INVOFF 0x20 ///< Display Inversion OFF +#define ILI9341_INVON 0x21 ///< Display Inversion ON +#define ILI9341_GAMMASET 0x26 ///< Gamma Set +#define ILI9341_DISPOFF 0x28 ///< Display OFF +#define ILI9341_DISPON 0x29 ///< Display ON + +#define ILI9341_CASET 0x2A ///< Column Address Set +#define ILI9341_PASET 0x2B ///< Page Address Set +#define ILI9341_RAMWR 0x2C ///< Memory Write +#define ILI9341_RAMRD 0x2E ///< Memory Read + +#define ILI9341_PTLAR 0x30 ///< Partial Area +#define ILI9341_VSCRDEF 0x33 ///< Vertical Scrolling Definition +#define ILI9341_MADCTL 0x36 ///< Memory Access Control +#define ILI9341_VSCRSADD 0x37 ///< Vertical Scrolling Start Address +#define ILI9341_PIXFMT 0x3A ///< COLMOD: Pixel Format Set + +#define ILI9341_FRMCTR1 \ + 0xB1 ///< Frame Rate Control (In Normal Mode/Full Colors) +#define ILI9341_FRMCTR2 0xB2 ///< Frame Rate Control (In Idle Mode/8 colors) +#define ILI9341_FRMCTR3 \ + 0xB3 ///< Frame Rate control (In Partial Mode/Full Colors) +#define ILI9341_INVCTR 0xB4 ///< Display Inversion Control +#define ILI9341_DFUNCTR 0xB6 ///< Display Function Control + +#define ILI9341_PWCTR1 0xC0 ///< Power Control 1 +#define ILI9341_PWCTR2 0xC1 ///< Power Control 2 +#define ILI9341_PWCTR3 0xC2 ///< Power Control 3 +#define ILI9341_PWCTR4 0xC3 ///< Power Control 4 +#define ILI9341_PWCTR5 0xC4 ///< Power Control 5 +#define ILI9341_VMCTR1 0xC5 ///< VCOM Control 1 +#define ILI9341_VMCTR2 0xC7 ///< VCOM Control 2 + +#define ILI9341_RDID1 0xDA ///< Read ID 1 +#define ILI9341_RDID2 0xDB ///< Read ID 2 +#define ILI9341_RDID3 0xDC ///< Read ID 3 +#define ILI9341_RDID4 0xDD ///< Read ID 4 + +#define ILI9341_GMCTRP1 0xE0 ///< Positive Gamma Correction +#define ILI9341_GMCTRN1 0xE1 ///< Negative Gamma Correction +//#define ILI9341_PWCTR6 0xFC + +#define MADCTL_MY 0x80 ///< Bottom to top +#define MADCTL_MX 0x40 ///< Right to left +#define MADCTL_MV 0x20 ///< Reverse Mode +#define MADCTL_NOTMV 0x00 ///< Reverse Mode + +#define MADCTL_ML 0x10 ///< LCD refresh Bottom to top +#define MADCTL_RGB 0x00 ///< Red-Green-Blue pixel order +#define MADCTL_BGR 0x08 ///< Blue-Green-Red pixel order +#define MADCTL_MH 0x04 ///< LCD refresh right to left + +// Color definitions +#define ILI9341_BLACK 0x0000 ///< 0, 0, 0 +#define ILI9341_NAVY 0x000F ///< 0, 0, 123 +#define ILI9341_DARKGREEN 0x03E0 ///< 0, 125, 0 +#define ILI9341_DARKCYAN 0x03EF ///< 0, 125, 123 +#define ILI9341_MAROON 0x7800 ///< 123, 0, 0 +#define ILI9341_PURPLE 0x780F ///< 123, 0, 123 +#define ILI9341_OLIVE 0x7BE0 ///< 123, 125, 0 +#define ILI9341_LIGHTGREY 0xC618 ///< 198, 195, 198 +#define ILI9341_DARKGREY 0x7BEF ///< 123, 125, 123 +#define ILI9341_BLUE 0x001F ///< 0, 0, 255 +#define ILI9341_GREEN 0x07E0 ///< 0, 255, 0 +#define ILI9341_CYAN 0x07FF ///< 0, 255, 255 +#define ILI9341_RED 0xF800 ///< 255, 0, 0 +#define ILI9341_MAGENTA 0xF81F ///< 255, 0, 255 +#define ILI9341_YELLOW 0xFFE0 ///< 255, 255, 0 +#define ILI9341_WHITE 0xFFFF ///< 255, 255, 255 +#define ILI9341_ORANGE 0xFD20 ///< 255, 165, 0 +#define ILI9341_GREENYELLOW 0xAFE5 ///< 173, 255, 41 +#define ILI9341_PINK 0xFC18 ///< 255, 130, 198 + +// Possible values for SPITFT.connection: +#define TFT_HARD_SPI 0 ///< Display interface = hardware SPI +#define TFT_SOFT_SPI 1 ///< Display interface = software SPI + + +#ifndef _TERMINAL_ +#define TFT_CS A0 +#define TFT_RST A1 +#define TFT_DC A2 +#define TFT_MOSI A3 // 11 +#define TFT_CLK A4 //13 +#define TFT_MISO A5 + +#else +//so we need to put CS on low, RST = A0, DC = A1, MOSI = A2, SCK = A3, MISO = not connected (NC) +#define TFT_CS -1 +#define TFT_RST A0 +#define TFT_DC A1 +#define TFT_MOSI A2 +#define TFT_CLK A3 +#define TFT_MISO -1 +#endif + + + + +#if defined(__AVR__) +#define DEFAULT_SPI_FREQ 2000000 ///< Hardware SPI default speed +#else +#define DEFAULT_SPI_FREQ 4000000L ///< Hardware SPI default speed +#endif + +#if defined(__AVR__) +#define AVR_WRITESPI(x) for (SPDR = (x); (!(SPSR & _BV(SPIF)));) +#endif + +#define TFT_TFTwidth 320 +#define TFT_TFTheight 240 +#define SCREEN_COLS 40 +#define SCREEN_ROWS 24 +#define LINE_WIDTH 6 +#define LINE_HEIGHT 8 +#define SCREEN_WIDTH SCREEN_COLS*LINE_WIDTH +#define SCREEN_HEIGHT SCREEN_ROWS*LINE_HEIGHT +#define MARGIN_TOP 3*LINE_HEIGHT +#define MARGIN_BOTTOM 3*LINE_HEIGHT +#define MARGIN_LEFT (TFT_TFTwidth - SCREEN_COLS*LINE_WIDTH)/2 +#define MARGIN_RIGHT (TFT_TFTwidth - SCREEN_COLS*LINE_WIDTH)/2 +#define SCREEN_TOP MARGIN_TOP +#define SCREEN_BOTTOM (TFT_TFTheight - MARGIN_BOTTOM) +#define SCREEN_LEFT MARGIN_LEFT +#define SCREEN_RIGHT (TFT_TFTwidth - MARGIN_RIGHT) +#define SCREEN_RECT_MARGIN 3 + + +// clang-format off + static const uint8_t PROGMEM initcmd[] = { + 0xEF, 3, 0x03, 0x80, 0x02, + 0xCF, 3, 0x00, 0xC1, 0x30, //Power control B (CFh) + 0xED, 4, 0x64, 0x03, 0x12, 0x81, //Power on sequence control (EDh) + 0xE8, 3, 0x85, 0x00, 0x78, //Driver timing control A (E8h) 0xE8, 3, 0x85, 0x00, 0x78, + 0xCB, 5, 0x39, 0x2C, 0x00, 0x34, 0x02, //Power control A (CBh) + 0xF7, 1, 0x20, //Pump ratio control (F7h) + 0xEA, 2, 0x00, 0x00, //Driver timing control B (EAh) 0xEA, 2, 0x00, 0x00, + ILI9341_PWCTR1 , 1, 0x23, // Power control VRH[5:0] + ILI9341_PWCTR2 , 1, 0x10, // Power control SAP[2:0];BT[3:0] + ILI9341_VMCTR1 , 2, 0x3e, 0x28, // VCM control + ILI9341_VMCTR2 , 1, 0x86, // VCM control2 + ILI9341_MADCTL , 1, 0x48, // Memory Access Control + ILI9341_VSCRSADD, 1, 0x00, // Vertical scroll zero + ILI9341_PIXFMT , 1, 0x55, + ILI9341_FRMCTR1 , 2, 0x00, 0x18, + ILI9341_DFUNCTR , 3, 0x08, 0x82, 0x27, // Display Function Control + 0xF2, 1, 0x00, // 3Gamma Function Disable + ILI9341_GAMMASET , 1, 0x01, // Gamma curve selected + ILI9341_GMCTRP1 , 15, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, // Set Gamma + 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00, + ILI9341_GMCTRN1 , 15, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, // Set Gamma + 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F, + ILI9341_SLPOUT , 0x80, // Exit Sleep + ILI9341_DISPON , 0x80, // Display on + 0x00 // End of list + }; + // clang-format on + + +#define TFT_PORTRAIT 1 +#define TFT_LANDSCAPE 0 + +#define CURSOR_RELATIVE 1 +#define CURSOR_ABSOLUTE 0 + +#define SCREEN_FULL_SCREEN 0 +#define SCREEN_CLIPPED 1 + +int tftPortrait = TFT_PORTRAIT; +//int tftPortrait = TFT_LANDSCAPE; + + +#undef USE_FAST_PINIO + +//SmartyKit Display Driver Class members +class SmartyKit_DisplayDriver +{ + public: + SmartyKit_DisplayDriver::SmartyKit_DisplayDriver(); + + SmartyKit_DisplayDriver::~SmartyKit_DisplayDriver() + { + if(spiClass) + spiClass->endTransaction(); + } + SPIClass *spiClass; + SPISettings spiSettings; + int connection; + int clipScreen; + uint8_t rotation; + int16_t _TFTwidth; //full TFT width + int16_t _TFTheight; //full TFT height + int16_t _workingScreenWidth; //screen area width: SCREEN_WIDTH + int16_t _workingScreenHeight; //screen area height: SCREEN_HEIGHT + int16_t _workingScreenTopMargin; + int16_t _workingScreenLeftMargin; + int16_t scrollLine; + int16_t cursor_x; + int16_t cursor_y; + int16_t screen_col; + int16_t screen_row; + + int16_t textsize_x; + int16_t textsize_y; + int8_t _dc; + int8_t _rst; ///< Reset pin # (or -1) + int8_t _cs; ///< Chip select pin # (or -1) + int8_t _sck; + int8_t _mosi; + int8_t _miso; + + uint16_t color = ILI9341_GREEN; + uint16_t bgColor = ILI9341_BLACK; + + + + //functions + void setup(); + void initSPI(void); + void sendCommand(uint8_t commandByte, const uint8_t *dataBytes, uint8_t numDataBytes); + void sendCommand(uint8_t commandByte, uint8_t *dataBytes = 0, uint8_t numDataBytes = 0); + void spiWrite(uint8_t b); // Write single byte as DATA + void writeCommand(uint8_t cmd); + void setAddrWindow(uint16_t x1, uint16_t y1, uint16_t w, uint16_t h); + inline void writeColor(uint16_t color, uint32_t len); + inline void startWrite(void); + inline void endWrite(void); + + void setRotation(uint8_t m); + void clearFullScreen(uint16_t color = ILI9341_WHITE); + void clearScreen(void); + void splashScreen(); + + void drawScreenRect(uint16_t color); + void drawScreenKeyboard(uint16_t color); + void drawHLine(uint16_t y, uint16_t color); + void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color); + inline void writeFillRectPreclipped(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color); + void writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color); + void scrollTo(uint16_t y); + void setScrollMargins(uint16_t top, uint16_t bottom); + void scrollToNextLine(void); + void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size, int keyboard = 0); + void writePixel(int16_t x, int16_t y, uint16_t color); + void setCursor(int16_t x, int16_t y, uint8_t relative = CURSOR_RELATIVE); + void print(uint8_t c, uint16_t color = ILI9341_GREEN); + + void printScreenBuffer(); + + inline void SPI_BEGIN_TRANSACTION(void){ }; + inline void SPI_END_TRANSACTION(void) { }; + void SPI_DC_HIGH(void); + void SPI_DC_LOW(void); + void SPI_CS_HIGH(void); + void SPI_CS_LOW(void); + void SPI_WRITE16(uint16_t w); + //for TFT_SOFT_SPI +// inline void SPI_MOSI_HIGH(void) { digitalWrite(_mosi, HIGH);}; +// inline void SPI_MOSI_LOW(void) { digitalWrite(_mosi, LOW);}; +// inline void SPI_SCK_HIGH(void) { digitalWrite(_sck, HIGH);}; +// inline void SPI_SCK_LOW(void) { digitalWrite(_sck, LOW);}; + +#ifndef _TERMINAL_ + inline void SPI_MOSI_HIGH(void) { PORTC = PORTC | B001000; }; //MOSI = A3 = PC3 + inline void SPI_MOSI_LOW(void) { PORTC = PORTC & B110111;}; //MOSI = A3 = PC3 + inline void SPI_SCK_HIGH(void) { PORTC = PORTC | B010000;}; //SCK = A4 = PC4 + inline void SPI_SCK_LOW(void) { PORTC = PORTC & B101111;}; //SCK = A4 = PC4 + + +#else + inline void SPI_MOSI_HIGH(void) { PORTC = PORTC | B000100; }; //MOSI = A2 = PC2 + inline void SPI_MOSI_LOW(void) { PORTC = PORTC & B111011;}; //MOSI = A2 = PC2 + inline void SPI_SCK_HIGH(void) { PORTC = PORTC | B001000;}; //SCK = A3 = PC3 + inline void SPI_SCK_LOW(void) { PORTC = PORTC & B110111;}; //SCK = A3 = PC3 + +#endif + + + + #if defined(_SMARTY_DEBUG_) + inline void beep() { tone(BEEPER_PIN, 880, 200); } + #endif + +}; + +volatile int screenRow = 0; +volatile int screenCol = 0; +char screenBuffer[SCREEN_ROWS][SCREEN_COLS]; + +SmartyKit_DisplayDriver::SmartyKit_DisplayDriver() +{ +} + + +void SmartyKit_DisplayDriver::setup() +{ +// #if defined(_SMARTY_DEBUG_) +// pinMode(BEEPER_PIN, OUTPUT); +// #endif + _dc = TFT_DC; + _rst = TFT_RST; + _cs = TFT_CS; + _sck = TFT_CLK; + _mosi = TFT_MOSI; + _miso = TFT_MISO; + + + //connection = TFT_HARD_SPI; + connection = TFT_SOFT_SPI; + + + initSPI(); + + // sendCommand(ILI9341_SWRESET); // Engage software reset + //delay(200); + + uint8_t cmd, x, numArgs; + const uint8_t *addr = initcmd; + while ((cmd = pgm_read_byte(addr++)) > 0) { + x = pgm_read_byte(addr++); + numArgs = x & 0x7F; + #if defined(_SMARTY_DEBUG_) + Serial.print(F("Initcmd: cmd = "));Serial.print(cmd, HEX); + Serial.print(F(", x = "));Serial.print(x, HEX); + Serial.print(F(", addr = "));Serial.print((uint8_t)addr, HEX); + Serial.print(F(", numArgs = "));Serial.print(numArgs, HEX); + Serial.println(); + #endif + sendCommand(cmd, addr, numArgs); + delay(10); + addr += numArgs; + if (x & 0x80) + delay(150); + } + + clipScreen = SCREEN_FULL_SCREEN; + scrollLine = 0; + cursor_x = 0; + cursor_y = 0; + textsize_x = 1; + textsize_y = 1; + _TFTwidth = ILI9341_TFTWIDTH; + _TFTheight = ILI9341_TFTHEIGHT; + _workingScreenWidth = SCREEN_WIDTH; + _workingScreenHeight = SCREEN_HEIGHT; + screen_col = 0; + screen_row = 0; + + color = ILI9341_GREEN; + bgColor = ILI9341_BLACK; + + if (tftPortrait == TFT_PORTRAIT) + { + setRotation(0); + clearFullScreen(ILI9341_BLACK); + //start right from the top-left corner - TO-DO: move to the screen centers + _workingScreenTopMargin = 0; + _workingScreenLeftMargin = 0; + + // drawScreenRect(ILI9341_WHITE); + } + if (tftPortrait == TFT_LANDSCAPE) + { + setRotation(3); + clearFullScreen(ILI9341_BLACK); + _workingScreenTopMargin = (_TFTheight - SCREEN_ROWS*LINE_HEIGHT)/2; + _workingScreenLeftMargin = (_TFTwidth - SCREEN_COLS*LINE_WIDTH)/2; + } + //drawing splash screen + splashScreen(); + + if (tftPortrait == TFT_PORTRAIT) + { + //set built-in hardware scrolling + setScrollMargins(0, ILI9341_TFTHEIGHT - SCREEN_HEIGHT); + clipScreen = SCREEN_CLIPPED; + + //drawScreenKeyboard(ILI9341_WHITE); + //drawScreenRect(ILI9341_WHITE); + + } + + setCursor(0,0); + clearScreen(); + print('#'); + print('>'); + + #if defined(_SMARTY_DEBUG_) + beep(); + #endif +} + +void SmartyKit_DisplayDriver::initSPI(void) +{ + + if (_cs >= 0) { + pinMode(_cs, OUTPUT); + digitalWrite(_cs, HIGH); // Deselect + delay(100); + //digitalWrite(_cs, LOW); // Select + } + + pinMode(_dc, OUTPUT); + digitalWrite(_dc, HIGH); // Data mode + + if (connection == TFT_HARD_SPI) + { + pinMode(SS, OUTPUT); + // SPI.begin(); + spiClass = &SPI; + + #if defined(_SMARTY_DEBUG_) + Serial.print(F("SmartyKit SPI freq = "));Serial.println(DEFAULT_SPI_FREQ, DEC); + #endif + + spiSettings = SPISettings(DEFAULT_SPI_FREQ, MSBFIRST, SPI_MODE0); + spiClass->begin(); + spiClass->beginTransaction(spiSettings); + pinMode(SS, OUTPUT); + } + else if (connection == TFT_SOFT_SPI) + { + pinMode(_mosi, OUTPUT); + digitalWrite(_mosi, LOW); + pinMode(_sck, OUTPUT); + digitalWrite(_sck, LOW); + if (_miso >= 0) { + pinMode(_miso, INPUT); + } + } + + + if (_rst >= 0) { + // Toggle _rst low to reset + pinMode(_rst, OUTPUT); + digitalWrite(_rst, HIGH); + delay(100); + digitalWrite(_rst, LOW); + delay(100); + digitalWrite(_rst, HIGH); + delay(200); + } +} + +inline void SmartyKit_DisplayDriver::startWrite(void) { + SPI_BEGIN_TRANSACTION(); + if (_cs >= 0) + SPI_CS_LOW(); +} + +inline void SmartyKit_DisplayDriver::endWrite(void) { + if (_cs >= 0) + SPI_CS_HIGH(); + SPI_END_TRANSACTION(); +} +void SmartyKit_DisplayDriver::setCursor(int16_t x, int16_t y, uint8_t relative = CURSOR_RELATIVE) { + if (relative == CURSOR_RELATIVE) + { + cursor_x = _workingScreenLeftMargin + x; + cursor_y = _workingScreenTopMargin + y; + } + else if (relative == CURSOR_ABSOLUTE) + { + cursor_x = x; + cursor_y = y; + } +} + +void SmartyKit_DisplayDriver::splashScreen() +{ + int logoWidth = 19; + //draw Smarty logo in the center + if (rotation == 0 || rotation == 3) + { + startWrite(); + setAddrWindow(_TFTwidth / 2 - logoWidth/2, _TFTheight / 2 - logoWidth/2, logoWidth, logoWidth); + //draw bgColor line to erase + for (uint16_t i = 0; i < logoWidth; i++) + { + for (int x = 0; x < logoWidth; x++) + SPI_WRITE16(ILI9341_WHITE); + } + //endWrite(); + + int logoInnerWidth = logoWidth/2; + //draw Smarty logo in the center + //startWrite(); + setAddrWindow(_TFTwidth / 2 - logoInnerWidth/2, _TFTheight / 2 - logoInnerWidth/2, logoInnerWidth, logoInnerWidth); + //draw bgColor line to erase + for (uint16_t i = 0; i < logoInnerWidth; i++) + { + for (int x = 0; x < logoInnerWidth; x++) + SPI_WRITE16(ILI9341_BLACK); + } + endWrite(); + + //delay(5000); + + delay(1500); + + //print company name + int chars = 24; + char company[chars] = "Made with \x03 by SmartyKit"; + //char company[chars] = "MADE WITH \x03 BY SMARTYKIT, INC."; + + setCursor(_TFTwidth / 2 - (chars*LINE_WIDTH)/2, _TFTheight - LINE_HEIGHT- 4, CURSOR_ABSOLUTE); + for (int i = 0; i < chars; i++) + { + if (company[i] == '\x03') //heart + print(company[i], ILI9341_RED); + else + print(company[i], ILI9341_WHITE); + delay(100); + } + + delay(1500); + } +} + +void SmartyKit_DisplayDriver::sendCommand(uint8_t commandByte, const uint8_t *dataBytes, + uint8_t numDataBytes) { + SPI_BEGIN_TRANSACTION(); + if (_cs >= 0) + SPI_CS_LOW(); + + #if defined(_SMARTY_DEBUG_) + Serial.print(F("PGM -> ")); + #endif + + SPI_DC_LOW(); // Command mode + spiWrite(commandByte); // Send the command byte + + SPI_DC_HIGH(); + for (int i = 0; i < numDataBytes; i++) { + Serial.print(F("arg")); Serial.print(i+1, DEC); Serial.print(F(" = ")); + uint8_t dataByte = pgm_read_byte(dataBytes++); + dataByte &= 0xFF; + spiWrite(dataByte); + } + + if (_cs >= 0) + SPI_CS_HIGH(); + SPI_END_TRANSACTION(); +} + +void SmartyKit_DisplayDriver::sendCommand(uint8_t commandByte, uint8_t *dataBytes, + uint8_t numDataBytes) { + SPI_BEGIN_TRANSACTION(); + if (_cs >= 0) + SPI_CS_LOW(); + + SPI_DC_LOW(); // Command mode + spiWrite(commandByte); // Send the command byte + + SPI_DC_HIGH(); + for (int i = 0; i < numDataBytes; i++) { + spiWrite(*dataBytes); // Send the data bytes + dataBytes++; + } + if (_cs >= 0) + SPI_CS_HIGH(); + SPI_END_TRANSACTION(); +} + +//Set the data/command line HIGH (data mode). +void SmartyKit_DisplayDriver::SPI_DC_HIGH(void) { +#if defined(USE_FAST_PINIO) + +#else // !USE_FAST_PINIO + digitalWrite(_dc, HIGH); +#endif // end !USE_FAST_PINIO + } + +//Set the data/command line LOW (command mode). +void SmartyKit_DisplayDriver::SPI_DC_LOW(void) { +#if defined(USE_FAST_PINIO) + +#else // !USE_FAST_PINIO + digitalWrite(_dc, LOW); +#endif // end !USE_FAST_PINIO + } + +void SmartyKit_DisplayDriver::SPI_CS_LOW(void) { +#if defined(USE_FAST_PINIO) + +#else // !USE_FAST_PINIO + digitalWrite(_cs, LOW); +#endif // end !USE_FAST_PINIO + } + +void SmartyKit_DisplayDriver::SPI_CS_HIGH(void) { +#if defined(USE_FAST_PINIO) + +#else // !USE_FAST_PINIO + digitalWrite(_cs, HIGH); +#endif // end !USE_FAST_PINIO + } + + +void SmartyKit_DisplayDriver::spiWrite(uint8_t b) { + if (connection == TFT_HARD_SPI) { +#if defined(__AVR__) + AVR_WRITESPI(b); +#else + char c = spiClass->transfer(b); + #if defined(_SMARTY_DEBUG_) + Serial.print(F("spiWrite = "));Serial.println(c, HEX); + #endif +#endif + } else if (connection == TFT_SOFT_SPI) + { + for (uint8_t bit = 0; bit < 8; bit++) { + if (b & 0x80) + SPI_MOSI_HIGH(); + else + SPI_MOSI_LOW(); + SPI_SCK_HIGH(); + b <<= 1; + SPI_SCK_LOW(); + } + } +} + +void SmartyKit_DisplayDriver::writeCommand(uint8_t cmd) { + SPI_DC_LOW(); + spiWrite(cmd); + SPI_DC_HIGH(); +} + +void SmartyKit_DisplayDriver::setRotation(uint8_t m) { + rotation = m % 4; // can't be higher than 3 + switch (rotation) { + case 0: + m = (MADCTL_MX | MADCTL_BGR); + _TFTwidth = ILI9341_TFTWIDTH; + _TFTheight = ILI9341_TFTHEIGHT; + break; + case 1: + m = (MADCTL_MV | MADCTL_BGR); + _TFTwidth = ILI9341_TFTHEIGHT; + _TFTheight = ILI9341_TFTWIDTH; + break; + case 2: + m = (MADCTL_MY | MADCTL_BGR); + _TFTwidth = ILI9341_TFTWIDTH; + _TFTheight = ILI9341_TFTHEIGHT; + break; + case 3: + // m = (MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR); + m = (MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR); + m = (MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_ML | MADCTL_MH | MADCTL_BGR); + _TFTwidth = ILI9341_TFTHEIGHT; + _TFTheight = ILI9341_TFTWIDTH; + break; + } + + sendCommand(ILI9341_MADCTL, &m, 1); +} + +void SmartyKit_DisplayDriver::clearFullScreen(uint16_t color = ILI9341_WHITE) +{ + startWrite(); + setAddrWindow(0, 0, _TFTwidth, _TFTheight); + for (int y = 0; y < _TFTheight; y++) + { + + for (int x = 0; x < _TFTwidth; x++) + { + //setAddrWindow(x, y, 1, 1); + SPI_WRITE16(color); + } + } + endWrite(); +} + +void SmartyKit_DisplayDriver::clearScreen(void) +{ + if (rotation == 3) + { + uint16_t color = ILI9341_BLACK; + uint16_t color2 = ILI9341_BLACK; + startWrite(); + setAddrWindow(_workingScreenLeftMargin, _workingScreenTopMargin, _workingScreenWidth, _workingScreenHeight); + for (int y = 0; y < _workingScreenHeight; y++) + { + for (int x = 0; x < _workingScreenWidth; x++) + { + //setAddrWindow(x, y, 1, 1); + if (y % 2 == 0) + SPI_WRITE16(color); + else + SPI_WRITE16(color2); + } + } + endWrite(); + } + else if (rotation == 0) + { + uint16_t color = ILI9341_BLACK; + uint16_t color2 = ILI9341_BLACK; + startWrite(); + setAddrWindow(_workingScreenLeftMargin, _workingScreenTopMargin, _workingScreenWidth, _workingScreenHeight); + for (int y = 0; y < _workingScreenHeight; y++) + { + for (int x = 0; x < _workingScreenWidth; x++) + { + //setAddrWindow(x, y, 1, 1); + if (y % 2 == 0) + SPI_WRITE16(color); + else + SPI_WRITE16(color2); + } + } + endWrite(); + } +} + +void SmartyKit_DisplayDriver::scrollTo(uint16_t y) { + + int scroll = y; + if (y > SCREEN_HEIGHT) + scroll = SCREEN_HEIGHT; + + startWrite(); + setAddrWindow(0, 0, SCREEN_WIDTH, scroll); + //draw bgColor line to erase + for (uint16_t i = 0; i < scroll; i++) + { + for (int x = 0; x < SCREEN_WIDTH; x++) + SPI_WRITE16(bgColor); + } + endWrite(); + //scroll screen + uint8_t data[2]; + data[0] = (y) >> 8; + data[1] = (y) & 0xff; + sendCommand(ILI9341_VSCRSADD, (uint8_t *)data, 2); + +} + +void SmartyKit_DisplayDriver::drawScreenRect(uint16_t color) +{ + if (rotation == 0 || rotation == 3) + { + startWrite(); + setAddrWindow(_workingScreenLeftMargin, _workingScreenTopMargin + _workingScreenHeight, _workingScreenWidth, 1); + for (int x = 0; x < _workingScreenWidth; x++) + SPI_WRITE16(color); + endWrite(); + } +} + + +void SmartyKit_DisplayDriver::drawScreenKeyboard(uint16_t color) +{ + int kbdRows = 5; + int kbdCols = 13; + int kbdTextSize = 2; + char kbd[kbdRows][kbdCols] = { + {'!','@','#','$','%','^', '&', '*', '(', ')', '_', '+', '<',}, + {'1','2','3','4','5', '6', '7', '8', '9', '0', '-', '=', '>',}, + {'Q','W','E','R','T','Y', 'U', 'I', 'O', 'P', ':', '[', ']',}, + {'A','S','D','F','G','H', 'J', 'K', 'L', ';', '"', '\'', '\\', }, + {'Z','X','C','V','B','N', 'M', '\x205', '\x245', '\x244', 'E', ',', '.', }, + }; + uint16_t kbdColor = ILI9341_WHITE; + int kbdMargin = 5; + int kbdMarginH = 6; + int kbdMarginV = 2; + + int keyboardHeight = kbdRows*LINE_HEIGHT + (kbdRows - 1)*kbdMargin; + + int kbdX = _workingScreenLeftMargin + LINE_WIDTH*kbdTextSize/2; + int kbdY = _workingScreenTopMargin + _workingScreenHeight + kbdMarginH; +// if (rotation == 0) +// { +// startWrite(); +// setAddrWindow(kbbX, kbdY, _workingScreenWidth, keyboardHeight); +// for (int x = 0; x < _workingScreenWidth*keyboardHeight; x++) +// SPI_WRITE16(kbdColor); +// endWrite(); +// } + for (int i = 0; i < kbdRows; i++) + { + for (int j = 0; j < kbdCols; j++) + { + drawChar(kbdX + j*(LINE_WIDTH*kbdTextSize + kbdMarginH), kbdY + i*(LINE_HEIGHT*kbdTextSize+kbdMarginV), kbd[i][j], + ILI9341_BLACK, ILI9341_WHITE, kbdTextSize, 1); + //drawChar(cursor_x, yLine, c, color, bgColor, textsize_x); + } + } + + //draw Space bar, Enter and Delete + int buttonsX = kbdX; + int buttonsY = kbdY + kbdRows*(LINE_HEIGHT*kbdTextSize+kbdMarginV); + int spaceCols = 6; + int spaceWidth = spaceCols*kbdTextSize*LINE_WIDTH + (spaceCols - 1)*kbdMarginH; + writeFillRect(buttonsX, buttonsY, spaceWidth, kbdTextSize * LINE_HEIGHT, ILI9341_WHITE); + + int enterCols = 3; + int enterWidth = enterCols*kbdTextSize*LINE_WIDTH + (enterCols - 1)*kbdMarginH; + writeFillRect(buttonsX + spaceWidth + kbdMarginH, buttonsY, enterWidth, kbdTextSize * LINE_HEIGHT, ILI9341_WHITE); + + +} + +void SmartyKit_DisplayDriver::drawHLine(uint16_t y, uint16_t color) +{ + //converting screen coordinates to memory coordinates + int yLine; + if ((scrollLine + y) < SCREEN_HEIGHT) + yLine = scrollLine + y; + else + yLine = (scrollLine + y) - SCREEN_HEIGHT; + + if (rotation == 0) + { + startWrite(); + setAddrWindow(0, yLine, SCREEN_WIDTH, 1); + for (int x = 0; x < SCREEN_WIDTH; x++) + { + SPI_WRITE16(color); + } + endWrite(); + } +} + +void SmartyKit_DisplayDriver::setScrollMargins(uint16_t top, uint16_t bottom) { + // TFA+VSA+BFA must equal 320 + if (top + bottom <= ILI9341_TFTHEIGHT) { + uint16_t middle = ILI9341_TFTHEIGHT - top - bottom; + uint8_t data[6]; + data[0] = top >> 8; + data[1] = top & 0xff; + data[2] = middle >> 8; + data[3] = middle & 0xff; + data[4] = bottom >> 8; + data[5] = bottom & 0xff; + sendCommand(ILI9341_VSCRDEF, (uint8_t *)data, 6); + } +} + +void SmartyKit_DisplayDriver::scrollToNextLine(void) +{ + if (rotation == 0 || rotation == 3) //build-in hardware scroll + { + //TO-DO: add margins - left and top + startWrite(); + setAddrWindow(0, scrollLine, _workingScreenWidth, LINE_HEIGHT); + //draw bgColor line to erase + for (uint16_t i = 0; i < LINE_HEIGHT; i++) + { + for (int x = 0; x < SCREEN_WIDTH; x++) + SPI_WRITE16(bgColor); + } + endWrite(); + + if ((scrollLine + LINE_HEIGHT) < SCREEN_HEIGHT) + scrollLine += LINE_HEIGHT; + else + scrollLine = (scrollLine + LINE_HEIGHT) - SCREEN_HEIGHT; + + //scroll screen + uint8_t data[2]; + data[0] = (scrollLine) >> 8; + data[1] = (scrollLine) & 0xff; + sendCommand(ILI9341_VSCRSADD, (uint8_t *)data, 2); + } +// else if (rotation == 3) +// { +// clearScreen(); +// //2 - shift text buffer for 1 line +// scrollScreenBuffer(1); +// //3 - redraw text from buffer +// printScreenBuffer(); +// } + +} + +void SmartyKit_DisplayDriver::setAddrWindow(uint16_t x1, uint16_t y1, uint16_t w, + uint16_t h) { + uint16_t x2 = (x1 + w - 1), y2 = (y1 + h - 1); + writeCommand(ILI9341_CASET); // Column address set + SPI_WRITE16(x1); + SPI_WRITE16(x2); + writeCommand(ILI9341_PASET); // Row address set + SPI_WRITE16(y1); + SPI_WRITE16(y2); + writeCommand(ILI9341_RAMWR); // Write to RAM +} + +void SmartyKit_DisplayDriver::SPI_WRITE16(uint16_t w) { + if (connection == TFT_HARD_SPI) { +#if defined(__AVR__) + AVR_WRITESPI(w >> 8); + AVR_WRITESPI(w); +#endif + +// char c = spiClass->transfer((uint8_t)w >> 8); +// #if defined(_SMARTY_DEBUG_) +// Serial.print(F("SPI_WRIE16 High = "));Serial.print(c, HEX); +// #endif +// c = spiClass->transfer((uint8_t)w); +// #if defined(_SMARTY_DEBUG_) +// Serial.print(F(", Low = "));Serial.println(c, HEX); +// #endif + } else if (connection == TFT_SOFT_SPI) { + for (uint8_t bit = 0; bit < 16; bit++) { + if (w & 0x8000) + SPI_MOSI_HIGH(); + else + SPI_MOSI_LOW(); + SPI_SCK_HIGH(); + SPI_SCK_LOW(); + w <<= 1; + } + } +} + +void SmartyKit_DisplayDriver::drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size, int keyboard = 0) +{ + uint8_t size_x = size; + uint8_t size_y = size; + + if ((x >= _TFTwidth) || // Clip right + (y >= _TFTheight) || // Clip bottom + ((x + 6 * size_x - 1) < 0) || // Clip left + ((y + 8 * size_y - 1) < 0)) // Clip top + { +// Serial.print(F("drawChar: clipping -> x = ")); Serial.print(x, DEC); Serial.print(F(", y = ")); Serial.print(y, DEC); +// Serial.print(F(", _TFTheight = ")); Serial.print(_TFTheight, DEC); Serial.println(); + return; + } +// if (!_cp437 && (c >= 176)) +// c++; // Handle 'classic' charset behavior + startWrite(); + //add first h-line for keyboard + if(keyboard == 1) + { + writeFillRect(x-2, y - 1, size_x*6+2, size_y, bg); + } + + for (int8_t i = 0; i < 5; i++) { // Char bitmap = 5 columns + uint8_t line = pgm_read_byte(&font[c * 5 + i]); + + for (int8_t j = 0; j < 8; j++, line >>= 1) { + if (line & 1) { + if (size_x == 1 && size_y == 1) + writePixel(x + i, y + j, color); + else + writeFillRect(x + i * size_x, y + j * size_y, size_x, size_y, + color); + } else if (bg != color) { + if (size_x == 1 && size_y == 1) + writePixel(x + i, y + j, bg); + else + writeFillRect(x + i * size_x, y + j * size_y, size_x, size_y, bg); + } + } + } + + if (bg != color) { // If opaque, draw vertical line for last column + if (size_x == 1 && size_y == 1) + writeFastVLine(x + 5, y, 8, bg); + else + writeFillRect(x + 5 * size_x, y, size_x, 8 * size_y, bg); + + //add first v-line for keyboard + if(keyboard == 1) + { + if (size_x == 1 && size_y == 1) + writeFastVLine(x - 2, y, 8, bg); + else + writeFillRect(x - 1*size_x, y, size_x, 8 * size_y, bg); + } + } + + endWrite(); + +} + +void SmartyKit_DisplayDriver::print(uint8_t c, uint16_t color = ILI9341_GREEN) +{ + + if (c == '\n') { // Newline? + cursor_x = _workingScreenLeftMargin; // Reset x to zero, + cursor_y += textsize_y * 8; // advance y one line + //screen_col = 0; + + int maxHeight = _TFTheight; + if (clipScreen == SCREEN_CLIPPED) + maxHeight = _workingScreenHeight + _workingScreenTopMargin; + if (cursor_y >= maxHeight ) + { + scrollToNextLine(); + cursor_y -= textsize_y * 8; + //screen_row = SCREEN_ROWS - 1; + } +// else +// screen_row++; + + } else if (c != '\r') { // Ignore carriage returns + if ((cursor_x + textsize_x * 6) > _workingScreenLeftMargin + _workingScreenWidth) { // Off right? + cursor_x = _workingScreenLeftMargin; // Reset x to zero, + // screen_col = 0; + cursor_y += textsize_y * 8; // advance y one line + } + + //autoscroll mode + int maxHeight = _TFTheight; + if (clipScreen == SCREEN_CLIPPED) + maxHeight = _workingScreenHeight + _workingScreenTopMargin; + if (cursor_y >= maxHeight) + { + scrollToNextLine(); + cursor_y -= textsize_y * 8; +// screen_row = SCREEN_ROWS - 1; + } +// else +// screen_row++; + + //converting screen coordinates to memory coordinates + int yLine; + if ((scrollLine + cursor_y) < maxHeight) + yLine = scrollLine + cursor_y; + else + yLine = (scrollLine + cursor_y) - maxHeight; + + drawChar(cursor_x, yLine, c, color, bgColor, textsize_x); + cursor_x += textsize_x * 6; // Advance x one char +// screen_col++; +// screenBuffer[screen_row][screen_col] = c; + } + + + } + + +void SmartyKit_DisplayDriver::writePixel(int16_t x, int16_t y, uint16_t color) +{ + // Clip first... + if ((x >= 0) && (x < _TFTwidth) && (y >= 0) && (y < _TFTheight)) { + // THEN set up transaction (if needed) and draw... + startWrite(); + setAddrWindow(x, y, 1, 1); + SPI_WRITE16(color); + endWrite(); + +// //save for screen buffer +// int col = x / LINE_WIDTH; +// int mask = (1 << (x % LINE_WIDTH)) - 1; +// if (color == ILI9341_BLACK) +// mask &= B00000000; +// else if (color == ILI9341_GREEN) +// mask |= B11111111; +// +// pixelBuffer[x][y] = pixelBuffer[x][y] || mask; + + } +} + +void SmartyKit_DisplayDriver::writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) +{ + if ((x >= 0) && (x < _TFTwidth) && h) { // X on screen, nonzero height + if (h < 0) { // If negative height... + y += h + 1; // Move Y to top edge + h = -h; // Use positive height + } + if (y < _TFTheight) { // Not off bottom + int16_t y2 = y + h - 1; + if (y2 >= 0) { // Not off top + // Line partly or fully overlaps screen + if (y < 0) { + y = 0; + h = y2 + 1; + } // Clip top + if (y2 >= _TFTheight) { + h = _TFTheight - y; + } // Clip bottom + writeFillRectPreclipped(x, y, 1, h, color); + } + } + } + +} +void SmartyKit_DisplayDriver::writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) +{ + if (w && h) { // Nonzero width and height? + if (w < 0) { // If negative width... + x += w + 1; // Move X to left edge + w = -w; // Use positive width + } + if (x < _TFTwidth) { // Not off right + if (h < 0) { // If negative height... + y += h + 1; // Move Y to top edge + h = -h; // Use positive height + } + if (y < _TFTheight) { // Not off bottom + int16_t x2 = x + w - 1; + if (x2 >= 0) { // Not off left + int16_t y2 = y + h - 1; + if (y2 >= 0) { // Not off top + // Rectangle partly or fully overlaps screen + if (x < 0) { + x = 0; + w = x2 + 1; + } // Clip left + if (y < 0) { + y = 0; + h = y2 + 1; + } // Clip top + if (x2 >= _TFTwidth) { + w = _TFTwidth - x; + } // Clip right + if (y2 >= _TFTheight) { + h = _TFTheight - y; + } // Clip bottom + writeFillRectPreclipped(x, y, w, h, color); + } + } + } + } + } +} + +inline void SmartyKit_DisplayDriver::writeFillRectPreclipped(int16_t x, int16_t y, + int16_t w, int16_t h, + uint16_t color) { + startWrite(); + setAddrWindow(x, y, w, h); + writeColor(color, (uint32_t)w * h); + endWrite(); +} + +void SmartyKit_DisplayDriver::printScreenBuffer() +{ + int cursor_x = _workingScreenLeftMargin; + int cursor_y = _workingScreenTopMargin; + setCursor(0, 0); //top-left of working screen + for (int i = 0; i < SCREEN_ROWS; i++) + { + for (int j = 0; j < SCREEN_COLS; j++) + { + + char c = screenBuffer[i][j]; + + if (c == '\n') { // Newline? + cursor_x = _workingScreenLeftMargin; // Reset x to zero, + cursor_y += textsize_y * 8; // advance y one line + + int maxHeight = _TFTheight; + if (clipScreen == SCREEN_CLIPPED) + maxHeight = _workingScreenHeight + _workingScreenTopMargin; + if (cursor_y >= maxHeight ) + { + scrollToNextLine(); + cursor_y -= textsize_y * 8; + } + + } else if (c != '\r') { // Ignore carriage returns + if ((cursor_x + textsize_x * 6) > _workingScreenLeftMargin + _workingScreenWidth) { // Off right? + cursor_x = _workingScreenLeftMargin; // Reset x to zero, + cursor_y += textsize_y * 8; // advance y one line + } + + //autoscroll mode + int maxHeight = _TFTheight; + if (clipScreen == SCREEN_CLIPPED) + maxHeight = _workingScreenHeight + _workingScreenTopMargin; + if (cursor_y >= maxHeight) + { + scrollToNextLine(); + cursor_y -= textsize_y * 8; + } + + //converting screen coordinates to memory coordinates + int yLine; + if ((scrollLine + cursor_y) < maxHeight) + yLine = scrollLine + cursor_y; + else + yLine = (scrollLine + cursor_y) - maxHeight; + + drawChar(cursor_x, yLine, c, color, bgColor, textsize_x); + cursor_x += textsize_x * 6; // Advance x one char + + //screenBuffer + } + } + } + print('\n'); +} + +inline void SmartyKit_DisplayDriver::writeColor(uint16_t color, uint32_t len) +{ + for (uint16_t i = 0; i < len; i++) + SPI_WRITE16(color); +} +//end: SmartyKit Display Driver Class + +// 40 keys 4x10 Keyboard Driver Class +class SmartyKit_40KeysKeyboardDriver +{ + public: + int colPressed; + int rowPressed; + const static int numRows = 4; + const static int numCols = 10; + int rowPins[numRows] = {0,1,2,3}; + int colPins[numCols] = {4,5,6,7,8,9,10,11,12,13}; + + char kbdTable[numRows][numCols] = { + {'1','2','3','4','5', '6', '7', '8', '9', '0',}, + {'Q','W','E','R','T','Y', 'U', 'I', 'O', 'P',}, + {'A','S','D','F','G','H', 'J', 'K', 'L', '\n', }, + {'\xE','Z', 'X','C','V','B','N', 'M', '\x20', '\x7F',}, + }; + + + SmartyKit_40KeysKeyboardDriver::SmartyKit_40KeysKeyboardDriver(){}; + SmartyKit_40KeysKeyboardDriver::~SmartyKit_40KeysKeyboardDriver(){}; + + void setup() + { + //setup + for (int row = 0; row < numRows; row++) + pinMode(rowPins[row], INPUT_PULLUP); + + for (int col = 0; col < numCols; col++) + { + pinMode(colPins[col], OUTPUT); + digitalWrite(colPins[col], HIGH); + } + } + + char read() + { + char c = '\x0'; + + + int val = 0; + + for (int col = 0; col < numCols; col++) + { + //searching with col = LOW + digitalWrite(colPins[col], LOW); + + for (int row = 0; row < numRows; row++) + { + val = digitalRead(rowPins[row]); + if (val == LOW) + { + c = kbdTable[row][col]; + colPressed = col; + rowPressed = row; + } + } + digitalWrite(colPins[col], HIGH); + } + // c = kbdTable[3][7]; + return c; + } +}; +//end: 40 keys 4x10 Keyboard Driver Class + + +/**********************************************************************/ +/**********************************************************************/ +/**********************************************************************/ +/**********************************************************************/ +/**********************************************************************/ + +//main code: setup() and loop() +SmartyKit_40KeysKeyboardDriver kbd; +SmartyKit_DisplayDriver tft; //creating instance of our Display Driver + + + +const int CPUwritesToVideoPortPin = 3; +const int VideoBIT7pin = 5; +int DataBus[8] = {6, 7, 8, 9, 10, 11, 12, 13}; +byte scan_code=0; + +void setup() { + pinMode(VideoBIT7pin, OUTPUT); + digitalWrite(VideoBIT7pin, HIGH); //wait until video setup is ready + + // starting TFT screen + tft.setup(); + + for (int count = 1; count <= 8; count++) { + pinMode(DataBus[count-1], INPUT); + }; + pinMode(CPUwritesToVideoPortPin, INPUT); + +#ifdef _TERMINAL_ + // Initialise the terminal + //term.cursorOff(); + // show hello world + term.setFont(TERMINAL_FONT_40_NORMAL_SINGLE); + term.setCursor(0,0); + term.printLine("Hello!\r\nI'm SmartyKit 1\r\nApple 1-compatible computer\r\nwww.smartykit.io\n"); + + term.printLine("\nType address to run:"); + term.printLine("F000R -> Woz's face demo"); + + term.printLine(""); + term.printLine(" 40x25 text output library for Arduino in two wire interface (I" "\xFD" "C) Mode"); + term.printLine(""); + // Show the 80 character positions + term.print("00000000001111111111222222222233333333334444444444555555555566666666667777777777"); + term.printLine("01234567890123456789012345678901234567890123456789012345678901234567890123456789"); +#endif + + + //attaching an IRQ to CPUwritesToVideoPortPin + attachInterrupt(1, videoCharInterrupt, RISING); + digitalWrite(VideoBIT7pin, LOW); //default state after restart = 0 (ready to print) +} + +void loop() { + //intentionally left blank +} + + +//interruption service routine (ISR) +void videoCharInterrupt(void) { + digitalWrite(VideoBIT7pin, HIGH); + + scan_code = 0; + for (int count = 1; count <= 8 ; count++) { + int pinValue = digitalRead(DataBus[count-1]); + scan_code |= pinValue << (count-1); + }; + scan_code = scan_code & 0x7F; //clear bit 7 + + if (scan_code == 0x7F) + { + digitalWrite(VideoBIT7pin, LOW); + return; //skip initial setup value + } + + if (scan_code == 0xD) + { + tft.print('\n'); + #ifdef _TERMINAL_ + term.printLine(""); + #endif + } + else + { + //make all symbols uppercase + if (scan_code >= 0x60) + scan_code -= 0x20; + + //print only visible chars, starting from blanc + if (scan_code >= 0x20) + { + tft.print((char)scan_code); + #ifdef _TERMINAL_ + term.send(scan_code); + #endif + } + //backspace + if (scan_code == 0x8) + { + //TV.print((char)scan_code); + } + + } + digitalWrite(VideoBIT7pin, LOW); +}