From aecdd172906d67f110f078b9cef04ef7c5b4f749 Mon Sep 17 00:00:00 2001 From: Computer construction kit SmartyKit <42343604+smartykit@users.noreply.github.com> Date: Mon, 31 Jan 2022 02:12:14 +0300 Subject: [PATCH 1/3] Adding TV Terminal library header and source file Adding TV out library header and source file by Dave Curran, Daryl Rictor and Grant Searle --- .../Terminal.cpp | 517 ++++++++++++++++++ .../Terminal.h | 124 +++++ 2 files changed, 641 insertions(+) create mode 100644 SmartyKit 1 basic drivers/SmartyKit1_VideoDriverBasic_TFT2.8_TV/Terminal.cpp create mode 100644 SmartyKit 1 basic drivers/SmartyKit1_VideoDriverBasic_TFT2.8_TV/Terminal.h diff --git a/SmartyKit 1 basic drivers/SmartyKit1_VideoDriverBasic_TFT2.8_TV/Terminal.cpp b/SmartyKit 1 basic drivers/SmartyKit1_VideoDriverBasic_TFT2.8_TV/Terminal.cpp new file mode 100644 index 0000000..2f32565 --- /dev/null +++ b/SmartyKit 1 basic drivers/SmartyKit1_VideoDriverBasic_TFT2.8_TV/Terminal.cpp @@ -0,0 +1,517 @@ +/* + * multi-mode tv out terminal library for Arduino + * + * Dave Curran 2013-09-06 + * + * Arduino Terminal Library - Dave Curran (www.tynemouthsoftware.co.uk) + * Concept and Microcontroller Firmware - Daryl Rictor, Grant Searle + * + * 2013-09-06 - V0.1 - Initial Release + * 2013-09-13 - V0.2 - Added 4 bit mode plus minor tidy up + * 2013-09-16 - V0.3 - Added I2C mode + * 2013-09-23 - V0.4 - I2C mode writing direct and bypassing Wire + * 2013-09-28 - V0.5 - Added font and graphics options + */ + +#include "Terminal.h" +#include "Arduino.h" + +// *************************************** +// * CONSTRUCTORS +// *************************************** + +// Initialise the display for 8 bit mode +// The pins can be any that are convenient. +Terminal::Terminal(uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7, uint8_t avail, uint8_t ack) +{ + // store pin numbers + _avail_pin = avail; + _ack_pin = ack; + + _data_pins[0] = d0; + _data_pins[1] = d1; + _data_pins[2] = d2; + _data_pins[3] = d3; + _data_pins[4] = d4; + _data_pins[5] = d5; + _data_pins[6] = d6; + _data_pins[7] = d7; + + // set pin modes + pinMode(_ack_pin, INPUT); + pinMode(_avail_pin, OUTPUT); + + for(uint8_t i=0; i<8; i++) + { + pinMode(_data_pins[i], OUTPUT); + digitalWrite(_data_pins[i], LOW); + } + + _4bit_mode = false; + _i2c_mode = false; + + clear(); +} + +// Initialise the display for 4 bit mode +// The pins can be any that are convenient. If using an Arduino, using pin 13 for ack will show activity +Terminal::Terminal(uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, uint8_t avail, uint8_t ack) +{ + // store pin numbers + _avail_pin = avail; + _ack_pin = ack; + + _data_pins[0] = d0; + _data_pins[1] = d1; + _data_pins[2] = d2; + _data_pins[3] = d3; + _data_pins[4] = 0; + _data_pins[5] = 0; + _data_pins[6] = 0; + _data_pins[7] = 0; + + // set pin modes + pinMode(_ack_pin, INPUT); + pinMode(_avail_pin, OUTPUT); + + for(uint8_t i=0; i<4; i++) + { + pinMode(_data_pins[i], OUTPUT); + digitalWrite(_data_pins[i], LOW); + } + + _4bit_mode = true; + _i2c_mode = false; + + clear(); +} + +// initialise for I2C mode +Terminal::Terminal() +{ + _4bit_mode = false; + _i2c_mode = true; + _transmitting = false; + + DDRC |= 0x30; // set the two I2C pins as outputs + + // Two wire speed initialisation + // SCL freq = CPU freq / (16+2*TWBR*Prescaler) + TWSR = 0; // Prescaler = 1 + TWBR = 12; // Bit rate 12 = 400KHz for 16MHz clk + + clear(); +} + +// *************************************** +// * Display control functions +// *************************************** + +// Clear the screen +void Terminal::clear() +{ + send(TERMINAL_CLEAR_SCREEN); +} + +// Blink the cursor +void Terminal::cursorBlink() +{ + send(TERMINAL_CURSOR_BLINKING); +} + +// use a solid cursor +void Terminal::cursorBlinkOff() +{ + send(TERMINAL_CURSOR_SOLID); +} + +// Change the cursor to a block +void Terminal::cursorBlock() +{ + cursorCustom(0xDB); +} + +// Change the cursor to an underscore (default) +void Terminal::cursorUnderscore() +{ + cursorCustom('_'); +} + +// no cursor +void Terminal::cursorOff() +{ + send(TERMINAL_CURSOR_SOLID); + cursorCustom(0x00); +} + +// set any character as the cursor character, 0x00 for off +void Terminal::cursorCustom(uint8_t c) +{ + send(TERMINAL_CURSOR_SET); + send(c); +} + +// set the font (use combinations of TERMAIN_FONT_x +void Terminal::setFont(uint8_t c) +{ + send(TERMINAL_SET_FONT); + send(c); +} + +// Set the cursor location +void Terminal::setCursor(uint8_t column, uint8_t row) +{ + setColumn(column); + setRow(row); +} + +// Set location to a given column +void Terminal::setColumn(uint8_t column) +{ + send(TERMINAL_SET_COLUMN); + send(column); +} + +// Set location to a given row +void Terminal::setRow(uint8_t row) +{ + send(TERMINAL_SET_ROW); + send(row); +} + +// Send the CTRL+LF pair +void Terminal::sendCRLF() +{ + send(TERMINAL_CARRIAGE_RETURN); + send(TERMINAL_LINE_FEED); +} + +// *************************************** +// * Graphics functions +// *************************************** + +// Set a pixel in 160x100 graphics - note any text on this line will be cleared +void Terminal::setPixel(uint8_t x, uint8_t y) +{ + if (x<160 && y<100) + { + send(TERMINAL_SET_PIXEL); + send(x); + send(y); + } +} + +// Clear a pixel in 160x100 graphics - note any text on this line will be cleared +void Terminal::clearPixel(uint8_t x, uint8_t y) +{ + if (x<160 && y<100) + { + send(TERMINAL_CLEAR_PIXEL); + send(x); + send(y); + } +} + +// draw a line from x1,y1 to x2,y2 +void Terminal::drawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) +{ + int xdiff = x2 - x1; + int ydiff = y2 - y1; + int maxdiff = max(abs(xdiff),abs(ydiff)); + for(int n=0; n= y) + { + setPixel(x + x0, y + y0); + setPixel(y + x0, x + y0); + setPixel(-x + x0, y + y0); + setPixel(-y + x0, x + y0); + setPixel(-x + x0, -y + y0); + setPixel(-y + x0, -x + y0); + setPixel(x + x0, -y + y0); + setPixel(y + x0, -x + y0); + + y++; + if(radiusError<0) + radiusError+=2*y+1; + else + { + x--; + radiusError+=2*(y-x+1); + } + } +} + +// fill a circle centred on x0,y0 with a radius of radius +void Terminal::fillCircle(uint8_t x0, uint8_t y0, uint8_t radius) +{ + for(int y=-radius; y<=radius; y++) + { + for(int x=-radius; x<=radius; x++) + { + if(x*x+y*y <= radius*radius) + { + setPixel(x0+x, y0+y); + } + } + } +} + +// clear a circle centred on x0,y0 with a radius of radius +void Terminal::clearCircle(uint8_t x0, uint8_t y0, uint8_t radius) +{ + for(int y=-radius; y<=radius; y++) + { + for(int x=-radius; x<=radius; x++) + { + if(x*x+y*y <= radius*radius) + { + clearPixel(x0+x, y0+y); + } + } + } +} + +// *************************************** +// * Send functions +// *************************************** + +// Print a string with a linefeed at the end +void Terminal::printLine(String s) +{ + print(s); + sendCRLF(); +} + +// Print a string +void Terminal::print(String s) +{ + // send character by character + for(unsigned int n=0; n + +// Control Codes +#define TERMINAL_CURSOR_HOME 0x01 +#define TERMINAL_CURSOR_SET 0x02 +#define TERMINAL_CURSOR_BLINKING 0x03 +#define TERMINAL_CURSOR_SOLID 0x04 +#define TERMINAL_SET_PIXEL 0x05 +#define TERMINAL_CLEAR_PIXEL 0x06 +#define TERMINAL_BACKSPACE 0x08 +#define TERMINAL_TAB 0x09 +#define TERMINAL_LINE_FEED 0x0A +#define TERMINAL_CLEAR_SCREEN 0x0C +#define TERMINAL_CARRIAGE_RETURN 0x0D +// Set column 0 to 79 (2nd uint8_t is the column number) +#define TERMINAL_SET_COLUMN 0x0E +// Set row 0 to 24 (2nd uint8_t is the row number) +#define TERMINAL_SET_ROW 0x0F +// Delete to the start of the line +#define TERMINAL_DELETE_BEFORE_LINE 0x10 +// Delete to the end of the line +#define TERMINAL_DELETE_AFTER_LINE 0x11 +// Delete to start of screen +#define TERMINAL_DELETE_BEFORE_PAGE 0x12 +// Delete to end of screen +#define TERMINAL_DELETE_AFTER_PAGE 0x13 +#define TERMINAL_SCROLL_UP 0x14 +#define TERMINAL_SCROLL_DOWN 0x15 +#define TERMINAL_SCROLL_LEFT 0x16 +#define TERMINAL_SCROLL_RIGHT 0x17 +#define TERMINAL_SET_FONT 0x18 + +// Treat next uint8_t as a character (to allow PC DOS char codes 1 to 31 to be displayed on screen) +#define TERMINAL_NEXT_IS_CHAR 0x1A +// ESC - reserved for ANSI sequences +#define TERMINAL_ESCAPE 0x1B +#define TERMINAL_CURSOR_RIGHT 0x1C +#define TERMINAL_CURSOR_LEFT 0x1D +#define TERMINAL_CURSOR_UP 0x1E +#define TERMINAL_CURSOR_DOWN 0x1F + +#define TERMINAL_DELETE 0x7F + +// font options +#define TERMINAL_FONT_40_CHAR 0x00 +#define TERMINAL_FONT_80_CHAR 0x01 +#define TERMINAL_FONT_NORMAL 0x00 +#define TERMINAL_FONT_BOLD 0x02 +#define TERMINAL_FONT_SINGLE_HEIGHT 0x00 +#define TERMINAL_FONT_DOUBLE_HEIGHT 0x04 +#define TERMINAL_FONT_GRAPHICS 0x80 + +#define TERMINAL_FONT_40_NORMAL_SINGLE 0x00 +#define TERMINAL_FONT_80_NORMAL_SINGLE 0x01 +#define TERMINAL_FONT_40_BOLD_SINGLE 0x02 +#define TERMINAL_FONT_80_BOLD_SINGLE 0x03 +#define TERMINAL_FONT_40_NORMAL_DOUBLE 0x04 +#define TERMINAL_FONT_80_NORMAL_DOUBLE 0x05 +#define TERMINAL_FONT_40_BOLD_DOUBLE 0x06 +#define TERMINAL_FONT_80_BOLD_DOUBLE 0x07 + +class Terminal +{ +public: + Terminal(uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7, uint8_t avail, uint8_t ack); + Terminal(uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, uint8_t avail, uint8_t ack); + Terminal(); + + void begin(); + void clear(); + void cursorBlink(); + void cursorBlinkOff(); + void cursorUnderscore(); + void cursorBlock(); + void cursorOff(); + void cursorCustom(uint8_t c); + void setFont(uint8_t c); + void setCursor(uint8_t column, uint8_t row); + void setColumn(uint8_t column); + void setRow(uint8_t row); + void setPixel(uint8_t x, uint8_t y); + void clearPixel(uint8_t x, uint8_t y); + void drawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2); + void clearLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2); + void drawBox(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2); + void fillBox(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2); + void clearBox(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2); + void drawCircle(uint8_t x0, uint8_t y0, uint8_t radius); + void fillCircle(uint8_t x0, uint8_t y0, uint8_t radius); + void clearCircle(uint8_t x0, uint8_t y0, uint8_t radius); + void sendCRLF(); + void printLine(String s); + void print(String s); + uint8_t send(uint8_t c); + +private: + uint8_t send4Bit(uint8_t c); + uint8_t send8Bit(uint8_t c); + uint8_t sendI2C(uint8_t c); + + uint8_t _data_pins[8]; // data outputs + uint8_t _avail_pin; // output, tell the display that new data is available + uint8_t _ack_pin; // input, the display acknowledges the input + bool _4bit_mode; // is the interface in 4 bit mode + bool _i2c_mode; // is this in I2C mode + bool _transmitting; // in the middle of an I2C packet +}; + +#endif + + From ca80cd3c89e52b66396a87d46b0549fe1a81121d Mon Sep 17 00:00:00 2001 From: Computer construction kit SmartyKit <42343604+smartykit@users.noreply.github.com> Date: Mon, 31 Jan 2022 02:24:32 +0300 Subject: [PATCH 2/3] Updated used libraries description --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5370028..33e117c 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,10 @@ SmartyKit Apple I replica drivers and software (http://www.smartykit.io/). All needed libraries included in repository in /Arduino/libraries ## Keyboard Driver -Keyboard driver uses Arduino PS2Keyboard library. +Keyboard driver uses Arduino PS2KeyAdvanced library. ## Video Driver -Video driver uses Arduino TVout library. +Video driver uses Arduino custom 2.8" TFT screen driver (based on Adafruit driver) and TV Terminal library. ## Software Emulator - POM 1 POM 1 cross-platform emulator by Verhille Arnaud to test SmartyKit 1 ROM with software. From 2c05bfe26e9b51d9b7b6dd10b1e90aeff788716c Mon Sep 17 00:00:00 2001 From: Computer construction kit SmartyKit <42343604+smartykit@users.noreply.github.com> Date: Mon, 31 Jan 2022 02:29:16 +0300 Subject: [PATCH 3/3] Beta version of 40 Keys custom keyboard driver This driver is used with 40 keys keyboard (10 cols and 4 rows, so 14 pins used) and sends char to CPU via serial connection (3 pins for Clock, Data and Latch). --- .../SmartyKit1_40keysKeyboardDriver.ino | 183 ++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 SmartyKit 1 basic drivers/SmartyKit1_KeyboardDriverBasic/SmartyKit1_40keysKeyboardDriver.ino diff --git a/SmartyKit 1 basic drivers/SmartyKit1_KeyboardDriverBasic/SmartyKit1_40keysKeyboardDriver.ino b/SmartyKit 1 basic drivers/SmartyKit1_KeyboardDriverBasic/SmartyKit1_40keysKeyboardDriver.ino new file mode 100644 index 0000000..e9d3cc8 --- /dev/null +++ b/SmartyKit 1 basic drivers/SmartyKit1_KeyboardDriverBasic/SmartyKit1_40keysKeyboardDriver.ino @@ -0,0 +1,183 @@ + /* SmartyKit 1 - 40 keys Keyboard driver v.1.0 + * http://www.smartykit.io/ + * Copyright (C) 2021, 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 . +*/ +#undef DEBUG + +const int KEYBOARD_ROWS = 4; +const int KEYBOARD_COLS = 10; + +const int keyboardRowsPins[KEYBOARD_ROWS] = {A2, A3, A4, A5}; +const int keyboardColsPins[KEYBOARD_COLS] = {4, 5, 6, 7, 8, 9, 10, 11, 12, 13}; + +const int latchPin = 2; +const int clockPin = A1; +const int dataPin = A0; + +const int keyReadyPin = 3; +static boolean BIT7flag = false; + +const char cShift = char(0x80); +const char cEnter = char(0x0D); +const char cSpace = char(0x20); +const char cDelete = char(0x7F); + +const unsigned char keyboard[KEYBOARD_ROWS][KEYBOARD_COLS] = +{ + {'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', cEnter,}, + {cShift,'Z','X','C','V','B','N', 'M',cSpace,cDelete,}, + }; + +const unsigned char keyboardShift[KEYBOARD_ROWS][KEYBOARD_COLS] = +{ + {'!','@','#','$','%','^','&','*','(',')',}, + {'Q','{','}','[',']','\\','_','-','+','=',}, + {'A','S','D','F','G',':',';','"','\'', cEnter,}, + {cShift,'Z','<','>',',','.','?', '/',cSpace,cDelete,}, + }; + +void setup() { + // put your setup code here, to run once: + for (int i=0; i < KEYBOARD_ROWS; i++) + pinMode(keyboardRowsPins[i], INPUT_PULLUP); + for (int i=0; i < KEYBOARD_COLS; i++) + pinMode(keyboardColsPins[i], OUTPUT); + + + pinMode(keyReadyPin, OUTPUT); + digitalWrite(keyReadyPin, HIGH); + + pinMode(latchPin, OUTPUT); + pinMode(clockPin, OUTPUT); + pinMode(dataPin, OUTPUT); + + #ifdef DEBUG + digitalWrite(latchPin, LOW); + shiftOut(dataPin, clockPin, MSBFIRST, '1'); # hex code 0x31 = 0011.0001b + digitalWrite(latchPin, HIGH); + #endif + + Serial.begin(115200); +} + +void loop() { + + // Read user input if available. + if (Serial.available()){ + char c = Serial.read(); + sendCharToKeyboardPort(c); + } + + // put your main code here, to run repeatedly: + char c = getKey(); + if(c) + { + if (c == cEnter) + Serial.println(); + else + Serial.print(c); + + sendCharToKeyboardPort(c); + } +} + +char getKey() +{ + char c = NULL; + bool bShift = getShift(); + for (int j=0; j < KEYBOARD_COLS; j++) + { + scanCol(j, bShift); + for (int i=KEYBOARD_ROWS-1; i >= 0; i--) //start from bottom-left corner with SHIFT button + { + int val = digitalRead(keyboardRowsPins[i]); + if (val == 0) + { + c = keyboard[i][j]; + if (c == cShift) + c = NULL; + else + { + if (bShift) + c = keyboardShift[i][j]; + } + delay(150); + } + } + } + return c; +} + +bool getShift() +{ + bool bShift = false; + int shiftCol = 0; // first column + int shiftRow = KEYBOARD_ROWS-1; // A row + + scanCol(shiftCol, false); + int val = digitalRead(keyboardRowsPins[shiftRow]); + if (val == 0) + bShift = true; + + return bShift; +} + +void scanCol(int col, bool bShift) +{ + if(bShift) + digitalWrite(keyboardColsPins[0], LOW); + + for (int i=0; i < KEYBOARD_COLS; i++) + { + if (i == col) + digitalWrite(keyboardColsPins[i], LOW); + else + digitalWrite(keyboardColsPins[i], HIGH); + + } +} + + + +void cpuReadsKeyboard(void) +{ + KeyboardBIT7_Disable(); +} + +void KeyboardBIT7_Enable() +{ + digitalWrite(keyReadyPin, HIGH); + BIT7flag = true; +} +void KeyboardBIT7_Disable() +{ + digitalWrite(keyReadyPin, LOW); + BIT7flag = false; +} + +void sendCharToKeyboardPort(char c) +{ +// while(BIT7flag == true) //wait untill the previous char is read by CPU +// delay(5); + + digitalWrite(keyReadyPin, LOW); + digitalWrite(latchPin, LOW); + shiftOut(dataPin, clockPin, MSBFIRST, c); + digitalWrite(latchPin, HIGH); + delay(30); + digitalWrite(keyReadyPin, HIGH); + KeyboardBIT7_Enable(); +}