VT100 terminal on a touchscreen

796 views
Skip to first unread message

James Moxham

unread,
Jun 18, 2018, 11:29:09 PM6/18/18
to RC2014-Z80
There are a number of terminals for VGA monitors but I've been wanting something a little smaller! This code is very experimental and only half finished but it demonstrates a few things as shown on the photo.
The hardware is a SSD1289 320x240 TFT display. These are on ebay for around $20. Also needs an Arduino Mega and an adaptor board (also on ebay). 
The big challenge has been getting the refresh speed fast enough for scrolling, hence the choice of a parallel 40 pin TFT rather than an SPI one. With a couple of extra sram chips, the display can be as fast as 30ms for a full colour bitmap dump.
Next challenge is Wordstar, which really needs a full 80 columns to look good. There are bigger displays out there but they cost more, so this display is 320 pixels wide, and for 80 columns that is only 4 pixels per letter, and one of those has to be the space between each letter. So this is a little font that is only 3x7 pixels!
The next step is being able to draw boxes easily, and for this the extended character set is very useful, as it has corners and single and double lines. I've spent a few weeks coding these characters in, pixel by pixel. Hopefully no-one will point me to code where someone else has already done this *grin*.
Then there are some tricks with VT100, which only has 8 colours; black, white, red, green, blue, yellow, cyan and magenta. There is no grey, but this is a trick to getting grey by using the 'dim/bright' attribute, and also the 'reverse' attribute, and then you can put black text on a grey background.
As it is relatively easy to do, the program can also read a full colour bitmap .bmp file off an SD card and display it on the screen.
Some of this is trying to work within the limitations of the Mega, which only has 8k of internal ram. For scrolling, the display needs to store 80x40 = 3200 bytes, and also each character needs an attribute byte, another 3200 bytes. By sacrificing some attributes (blink and underscore), it should be possible to pack all the attribute data into a byte - 1 bit for reverse, 1 bit for dim/bright (foreground only), 3 bits for foreground colour and 3 bits for background colour. 
I haven't written the code that decodes the escape sequences but I think this has been done elsewhere and should be able to be ported in. 
An Arduino Mega has several serial ports. It is easy to add a PS/2 keyboard. There could also be the opportunity to write some more VT100 sequences to do things like open a file on the SD card and dump out some bytes, which could be a useful way of transferring files from FAT SD card files into CP/M disk images. It should be possible to get the touchscreen working and turn this into serial data that CP/M could process. 
Code below is the function to print the little grey on blue window at the bottom of the picture. (Normally this sort of routine would be on a CP/M program and sending escape commands)

The rest of the code is very much only half finished. I need to write the code to do scrolling on part/full screen and also to decode the VT100 commands. 

Back to coding!

void windowTest()
{
  vt100setAttribute(0); // reset
  box(40,19,21,10,34,44); // blue background
  box(43,22,15,6,30,40); // black behind the window
  vt100setAttribute(2); // dim
  vt100setAttribute(7); // reverse
  boxSingle(42,21,14,6,37,40); // want black on gray, so set foreground to dim, foreground to white, background to black and reverse
  vt100locate(46,23);
  const static uint8_t s1[] PROGMEM = "Window"; // code to print strings without using any precious internal ram
  vt100printString3x7(getString(s1));
  vt100setAttribute(0); // reset all
  vt100setAttribute(37); // white foreground
  vt100setAttribute(40); // black foreground
  vt100locate(45,25);
  const static uint8_t s2[] PROGMEM = " < OK > "; 
  vt100printString3x7(getString(s2));
}
VT100June19.JPG

Jonathan Lake-Thomas

unread,
Jun 19, 2018, 7:02:04 AM6/19/18
to RC2014-Z80

James Moxham

unread,
Jun 19, 2018, 7:49:17 AM6/19/18
to RC2014-Z80


On Tuesday, 19 June 2018 20:32:04 UTC+9:30, Jonathan Lake-Thomas wrote:
Have you seen this?

Reading through it now. I have a few of those displays. They are slightly smaller than the ones I am using. Thinking ahead, it would be great to have a range of screen sizes available - from small touchscreens up to VGA size screens.  

Alan Cox

unread,
Jun 19, 2018, 9:01:40 AM6/19/18
to rc201...@googlegroups.com
You don't need a space between each letter always. For wide letters
like 'm' you can get away with it (or at least you could on a TV), and
it worked ok on the Amstrad NC100 lcd screen back when I could
actually read a font that small. On colour displays some of the
fancier small font setups use antialiasing but I'm not sure it helps.

There are a range of 6x4 and similar open source fonts around but none
with graphic symbols I know of.

BTW if you look how many other terminals and early 6845 based systems
packed their attributes it was common to instead drop reverse and
dim/bright. You don't need reverse because you can swap the colours
over, and you don't need bright because you can use a dimmer colour.
As you can't query a character or partially update it nobody can tell
what is going on!

Alan
PS: VT100 doesn't have colour - that came in with the VT241

James Moxham

unread,
Jun 19, 2018, 8:54:21 PM6/19/18
to RC2014-Z80
Some great points there Alan.
Agree re some characters not needing a space between letters. Some spill into the space area, eg accents and underlines. Some of the extended characters deliberately go into the space, eg box drawing and blocks. So the font is 3x7 but some characters use the full 8x4.
Agree it is not VT100. Is ANSI a better descriptor? https://en.wikipedia.org/wiki/ANSI_escape_code
Interesting that some VT100 examples allow line drawing and boxes. That could be useful.
Re the limitations of the Arduino Mega, 3200 bytes for text and 3200 bytes for 'attributes'.
Could use the escape numbers 90 to 97 and 100 to 107 to do foreground and background. Good idea to drop reverse. Thinking simplistically, 4 bits for foreground and 4 bits for background, and each is 3 bits for colour and then 1 bit for dim/bright, so 16 colours.

Further down that page is a discussion about 256 colours using lookup tables. That could certainly fit within a 3200 byte 'attribute' ram space, and could be very useful for games. Not sure if anyone is running games on the RC2014?

Then of course can always invent more commands to draw pixels and lines of any colour, if happy to not store these anywhere so can't scroll. And it is simple to move a bitmap to the screen, so things like drawing a keyboard on the screen for touchscreen is actually easier dumping a whole screen bitmap than drawing each box/letter/key. 

Much to think about!  

Spencer Owen

unread,
Jun 20, 2018, 6:21:00 AM6/20/18
to rc201...@googlegroups.com
The PiGFX software for the Pi Serial Terminal is ANSI and that works pretty good.

As for games, well, the only one I regularly use is Snake, although when I use that to show off the RC2014 at Maker Faire type events, I normally get complaints (from younger people generally) that it runs too fast!  That takes advantage of the ANSI escape sequences, and although the graphics are blocky, it does run really smoothly :)

Cheers

Spencer

--
You received this message because you are subscribed to the Google Groups "RC2014-Z80" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rc2014-z80+unsubscribe@googlegroups.com.
To post to this group, send email to rc201...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/a386ff28-4e22-4b96-ab32-9ff310339a3b%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Alan Cox

unread,
Jun 20, 2018, 8:51:26 PM6/20/18
to rc201...@googlegroups.com
>> Agree it is not VT100. Is ANSI a better descriptor?

Probably - the ANSI spec actually predates the VT100. After it was
specified everyone said it was overcomplex and couldn't be
implemented. Once the 8080 came along however it was possible. Nowdays
it's become an ISO spec but also an ECMA one (and usefully ECMA specs
are free) - its ECMA 35, 43 and 48 plus other stuff such as being able
to set the scrolling region.

> Interesting that some VT100 examples allow line drawing and boxes. That could be useful.

The VT terminals grew over time. The line drawing characters allowed
you to do nice looking 'form' interfaces.

After that they added 96 redefinable graphic characters (really handy
- we had an really cool 'pacman' for VT240 terminals because not only
did they have graphics symbols but pacman doesn't have to do many
screen updates !)

The later ones also supported 'sixel' plotting where you could control
the display in six pixel wide horizontal strips. This let you do
amazing things but took all day. In fact at 9600 baud the most useful
thing for it was to freak people out when they saw a terminal with a
picture on it 8)

The final thing was REGIS (VT125 etc) which allowed you to do stuff
like graph and chart drawing with vector graphics plotting including
things like circles, polygons, lines etc and with fills.

From a gaming perspective the VT420 codes included some really nice
extras - fill rect with char , erase rect to space, copy rectangular
area (really good for
graphical movement of stuff), as well as protecting characters and
selective erase. That was meant for form filling but also happened to
be brilliant for
'delete all the sprites/explosions I just drew and leave the background'

> background. Good idea to drop reverse. Thinking simplistically, 4 bits for
> foreground and 4 bits for background, and each is 3 bits for colour and then
> 1 bit for dim/bright, so 16 colours.

RGBI.

The VT340 uses 16 colours

Black
Blue
Red
Green
Magenta
Cyan
Yellow
Gray 50%
Gray 25%
Dull Blue
Dull Red
Dull Green
Dull Magenta
Dull Cyan
Dull Yelow
Gray 75%

oddly enough there is no 'white'



A real VT100 (mono) had 3072 bytes of RAM, and 8K ROM for the terminal
software. Just under 2.5K was used for the display itself. When you
had the AVO fitted (attribute support, 132x24 display) that added
another 1K of RAM for the display and a 4K x 4bit memory for the
attributes. I think some of the other features must have meant there
was also a per line attribute of some kind (double height top, bottom
and double width

The VT102 is very similar but added a few really useful things that
the VT100 demonstrated would be good tweaks. Most importantly it added
insert line/delete line which really improved editors.

The VT220 had 8K of RAM I believe and an 8051

The graphical terminals had a chunk more memory in a separate plane or
planes. The VT125 for example has 48K of video RAM. So I guess you
could do something like REGIS or sixels but only without
scrolling/insert/delete line etc.


For most things the really useful stuff in the later VT terminals was
the redefinable font, although the pixel stretching logic made it
'interesting' to design one. As it changed the character maps only it
worked on the terminals without loads of graphics memory as well.

There is also a really useful torture tester (vttest) for checking
your emulation. Most 'real' clone terminals fail bits of it 8)

Alan

James Moxham

unread,
Jun 22, 2018, 10:34:43 AM6/22/18
to RC2014-Z80
Some great advice there Alan. Working through things and adding them to the code now.
With colours, there seems to be lots of standards. I initially have made it very simple - 3 bits for colour, 1 bit for bright/dim and then 4 bits for foreground and 4 bits for background. Use ANSI codes 40 to 47 for dim background and 100 to 107 for bright background. That gives all 16 colours. 
The website https://en.wikipedia.org/wiki/ANSI_escape_code#3/4_bit in "Colors" seems to have all sorts of different actual RGB values. I guess I have to make a choice so went for the column "CMD" which seem to be the most logical, eg 128 for dim, 255 for bright. There are 4 greyscale colours - black 0,0,0, dimwhite 192,192,192, brightblack 128,128,128 and brightwhite 255,255,255. 
Now it is pretty straightforward to draw DOS-like windows, which use a lot of dim blue background, grey windows with black text, and white text on either black or grey background. 
Next step is maybe looking at the 256 color section. I'm not sure I can completely code that as there is only enough ram for one byte per character for attribute. So can only store that as a foreground color, and the background would be black. But there are several boxes of varying pixel densities that can be used to give even more colours.
I like the idea of being able to program in characters. That could be handy for games, to preprogram in sprites. 

James Moxham

unread,
Jun 22, 2018, 10:06:50 PM6/22/18
to RC2014-Z80
This picture is probably best viewed from the other side of the room while squinting! Glorious 4 bit ANSI colours. Use the extended character 223 which is a box with the top half 4x4 pixels in the foreground colour, and the bottom 4x4 in the background colour. Three bits for each colour and 1 bit for bright/dim.
Take an image, shrink to 80x60 pixels then resample with the 16 'windows' colours. Two pixels per character. Can store this in 2400 attribute bytes. The text bytes are all 223, and theoretically, they could store something different and improve the colour depth.
Next step is adding the scrolling commands. 
PICT0021.JPG

James Moxham

unread,
Jun 27, 2018, 2:35:33 AM6/27/18
to RC2014-Z80
The ultimate goal with this project is a screen to run Wordstar but I have to confess getting a little distracted with the graphics capabilities of the old-school ANSI terminals. This is 8 bit 'xterm' colour where 0-15 are the original dim and bright colours, then 16 to 231 are 6 values per colour, in a 6x6x6 cube, and then 232 to 255 are grayscale in 24 values.
So we can read in a standard bitmap file from an SD card (pre sized to 80x60) and then translate it to the closest match colours using a 'least squares' algorithm. The resulting file is 4800 bytes long and can be quickly saved and read from an SD card. 
Just to test this is compatible with the ANSI standard, the screen can be converted to Esc[ sequences and sent to a terminal program. In this case I am using Teraterm with the default Terminal font. For each character, set the foreground colour, then the background colour, then send character 223 which is a half block. 
I also have scrolling working. There are a few more escape commands needed to get Wordstar working (easiest way to test this is to fire up Wordstar and then capture the output in a terminal that doesn't understand the ANSI sequences, eg the Arduino terminal).
I still have a bit of a crazy idea that CP/M programs can work in colour. 
I've attached the code (warts and all) if anyone is interested in getting an Arduino Mega and a screen. 
Back to coding!
TouchscreenMegaNoRam_June27_2018.zip
PICT0023.JPG

Tom Szolyga

unread,
Jun 28, 2018, 11:43:57 PM6/28/18
to RC2014-Z80
Hi James,

I am interested in following your work and experimenting.  I bought a Mega board and display package from Amazon: 


I have loaded your code into it via the Arduino IDE, the screen just stays white.  I have discovered that the product ships with EITHER a SSD1289 or an ILI9341.  Apparently the devices are "interchangeable".  The boards I got have the ILI9341.  The demo code for it runs just fine, showing graphics, color drawing and painting.  I think this means the board and LCD are okay.  Any thoughts about what I could try with your code?

I looked at the demo code for the board.  It includes <UTFT.h>.  From the documentation, that library has a collection of routines to manipulate the LCD display.  

Finally, I looked for the original source code at the URL in your code, put I could not find it.  Is there a better place to look?

Best regards,
Tom
 
71ESIAqjDUL._SL1000_.jpg

James Moxham

unread,
Jun 29, 2018, 11:52:45 PM6/29/18
to RC2014-Z80
Hi Tom,

I have substantially rewritten the standard code to make it a lot faster. Going back a few years, I think I had some code for the Propeller chip that could run both types of display. The main difference is in the setup routines. The actual code to print a pixel ended up being rather similar. I'll see if I can dig that old code out as there could be a good argument for writing code for several displays (there is a third type ?SSD1963 that also would be useful as they came in larger sizes, up to 7"). Might take a few days while I rummage around in an old hard drive :)
Do you have a link to the code you are using? Need to strip it right back to the absolute simplest thing, which is to initiate the display and then print just one pixel. 
Cheers, James 
 

 

James Moxham

unread,
Jun 30, 2018, 12:14:47 AM6/30/18
to RC2014-Z80
Quickly rummaging round through the code for your display, I found this line 
#ifndef DISABLE_SSD1289
#include "tft_drivers/ssd1289/initlcd.h"
#endif

and ditto one for the SSD1963 and lots of others. There are lots of .h files in the 'drivers' folder. 
Hopefully that means there is a 'cut and paste' solution for the code. Will think about it a bit more.

James Moxham

unread,
Jun 30, 2018, 9:01:30 PM6/30/18
to RC2014-Z80
Below is a very simple demonstration to draw a box. All unused code has been removed and there are no dependent files.
I am fairly sure that all the pinouts of these 40 pin displays are the same. The only differences are that some are 3V and some are 5V, but the display adaptor has resistors on each pin to allow for this. So all the code that talks to the ports will be the same for all displays. The things that are different are initiating the display, setting the column and row addresses and changing from portrait to landscape. So to list the routines that need to be changed for each display, these will be:
lcdInitSSD1289()
portrait()
landscape()
lcdAddressSet()

This makes the whole process a bit more manageable as that is only four routines. 
In the link to Tom's board above are a zip file to download, and in that is a folder with drivers, and in there are some .h files and (I think) some code for each type of display. So the next step would be to find the routines for the above four functions and change the hex values. 
I have to go to work now but later I'll see if I can dig out some of the other brands of displays I have as I think I might have the one Tom has.



// SSD1289 very simple demo, draw a box. 

uint8_t isOrientationLanscape = 0; // portrait mode = default, 1 = landscape

void setup()
{
   //Serial.begin(115200); // for debugging
   lcdPortDirection(); // enable mega pins for I/O
   lcdInitSSD1289();  // initiate the display
   clearBlacklandscape(); // clear the screen
   fastBox(150,110,20,20,B11111111,B11111111); // draw a white box RRRRRGG GGGBBBBB
}
 
void loop()
{

}
  
// **************** low level display control *********
// *** keep all PORT and DDR commands in a group here, easier to change if change boards

void lcdPortDirection() {
      DDRA = B11111111; // port A VH = all outputs, high data byte
      DDRC = B11111111; // port C VL = all outputs, low data byte
      DDRD = B10000000; // port D bit 7 output = RS
      DDRG = B00000111; // port G bit 0=reset, 1=CS, 2=WR
}

void lcdResetLow() {
      PORTG = PORTG & B11111110;   // LCD_REST low
}

void lcdResetHigh() {
      PORTG = PORTG | B00000001;   // LCD_REST high
}

void lcdCSLow() {
      PORTG = PORTG & B11111101;   // LCD_CS low
}

void lcdCSHigh() {
      PORTG = PORTG | B00000010;   // LCD_CS high
}

void lcdRSLow() {
      PORTD = PORTD & B01111111;   // LCD_RS low
}

void lcdRSHigh() {
      PORTD = PORTD | B10000000; // LCD_RS high
}

void lcdWriteBus(uint8_t VH,uint8_t VL)
{
      PORTA = VH;                  // faster by writing directly to the port (original code used digitalWrite). Other routines are not so time critical
      PORTC = VL;                  
      PORTG = PORTG & B11111011;   // LCD_WR low
      PORTG = PORTG & B11111011;   // LCD_WR low small hack, if write this three times it is faster than adding in a 1 microsecond delay. Two times is too fast for the display
      PORTG = PORTG & B11111011;   // LCD_WR low
      //delayMicroseconds(1);        // small delay as a Mega is a bit fast for the display, but writing three times above is the same and a bit more accurate
      PORTG = PORTG | B00000100;   // LCD_WR high
}

void fastBox(uint16_t orgX, uint16_t orgY, uint16_t cols, uint16_t rows, uint8_t VH, uint8_t VL) // draw a box or rectangle, send out the pixel data just once
{
    uint32_t i;
    uint32_t pixels;
    uint32_t colsL,rowsL;
    lcdStartDraw(orgX, orgY, cols, rows);
    rowsL=rows; // cast to a long
    colsL=cols;
    pixels = rowsL * colsL; 
    PORTA = VH;                  // faster by writing directly to the port (original code used digitalWrite). Other routines are not so time critical
    PORTC = VL;                  // only write the color data once, then toggle the write pin n times
    delayMicroseconds(1); 
    for(i=0;i<pixels;i++)
    {
      PORTG = PORTG & B11111011;   // LCD_WR low
      PORTG = PORTG & B11111011;   // LCD_WR low small hack, if write this three times it is faster than adding in a 1 microsecond delay. Two times is too fast for the display
      PORTG = PORTG & B11111011;   // LCD_WR low
      PORTG = PORTG | B00000100;   // LCD_WR high
    }
    lcdFinishDraw();
}
 
// **** end all Port dependent code ***
 
void lcdWriteCommand(uint8_t VH, uint8_t VL)  
{   
  lcdRSLow();
  lcdWriteBus(VH, VL);
}
 
void lcdWriteData(uint8_t VH, uint8_t VL) // see also drawpixel and start and finishdraw as these are faster
{
  lcdRSHigh();
  lcdWriteBus(VH, VL);
}

void lcdWriteCommandData(int com,int dat)
{
     lcdWriteCommand(com>>8,com);
     lcdWriteData(dat>>8,dat);
}
 
void lcdAddressSet(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2)
{
    if (isOrientationLanscape) {
      lcdWriteCommandData(0x44,(y2 << 8) + y1 );   //Column address start2
      lcdWriteCommandData(0x45,x1);                 //Column address start1
      lcdWriteCommandData(0x46,x2);                 //Column address end2
      lcdWriteCommandData(0x4e,y1);                 //Column address end1
      lcdWriteCommandData(0x4f,x1);                 //Row address start2
    }
    else {
      lcdWriteCommandData(0x44,(x2 << 8) + x1 );   //Column address start2
      lcdWriteCommandData(0x45,y1);                 //Column address start1
      lcdWriteCommandData(0x46,y2);                 //Column address end2
      lcdWriteCommandData(0x4e,x1);                 //Column address end1
      lcdWriteCommandData(0x4f,y1);                 //Row address start2
    }
    lcdWriteCommand(0x00,0x22);   
}

void lcdInitSSD1289(void)
{
    lcdResetHigh(); 
    delay(5); 
    lcdResetLow();
    delay(15);
    lcdResetHigh();
    delay(15);
    lcdWriteCommandData(0x0000,0x0001);    delay(1);  //打开晶振
    lcdWriteCommandData(0x0003,0xA8A4);    delay(1);   //0xA8A4
    lcdWriteCommandData(0x000C,0x0000);    delay(1);   
    lcdWriteCommandData(0x000D,0x080C);    delay(1);   
    lcdWriteCommandData(0x000E,0x2B00);    delay(1);   
    lcdWriteCommandData(0x001E,0x00B7);    delay(1);   
    lcdWriteCommandData(0x0001,0x2B3F);    delay(1);   //驱动输出控制320*240  0x6B3F
    lcdWriteCommandData(0x0002,0x0600);    delay(1);
    lcdWriteCommandData(0x0010,0x0000);    delay(1);
    lcdWriteCommandData(0x0011,0x6070);    delay(1);        //0x4030           //定义数据格式  16位色 
    lcdWriteCommandData(0x0005,0x0000);    delay(1);
    lcdWriteCommandData(0x0006,0x0000);    delay(1);
    lcdWriteCommandData(0x0016,0xEF1C);    delay(1);
    lcdWriteCommandData(0x0017,0x0003);    delay(1);
    lcdWriteCommandData(0x0007,0x0233);    delay(1);        //0x0233       
    lcdWriteCommandData(0x000B,0x0000);    delay(1);
    lcdWriteCommandData(0x000F,0x0000);    delay(1);        //扫描开始地址
    lcdWriteCommandData(0x0041,0x0000);    delay(1);
    lcdWriteCommandData(0x0042,0x0000);    delay(1);
    lcdWriteCommandData(0x0048,0x0000);    delay(1);
    lcdWriteCommandData(0x0049,0x013F);    delay(1);
    lcdWriteCommandData(0x004A,0x0000);    delay(1);
    lcdWriteCommandData(0x004B,0x0000);    delay(1);
    lcdWriteCommandData(0x0044,0xEF00);    delay(1);
    lcdWriteCommandData(0x0045,0x0000);    delay(1);
    lcdWriteCommandData(0x0046,0x013F);    delay(1);
    lcdWriteCommandData(0x0030,0x0707);    delay(1);
    lcdWriteCommandData(0x0031,0x0204);    delay(1);
    lcdWriteCommandData(0x0032,0x0204);    delay(1);
    lcdWriteCommandData(0x0033,0x0502);    delay(1);
    lcdWriteCommandData(0x0034,0x0507);    delay(1);
    lcdWriteCommandData(0x0035,0x0204);    delay(1);
    lcdWriteCommandData(0x0036,0x0204);    delay(1);
    lcdWriteCommandData(0x0037,0x0502);    delay(1);
    lcdWriteCommandData(0x003A,0x0302);    delay(1);
    lcdWriteCommandData(0x003B,0x0302);    delay(1);
    lcdWriteCommandData(0x0023,0x0000);    delay(1);
    lcdWriteCommandData(0x0024,0x0000);    delay(1);
    lcdWriteCommandData(0x0025,0x8000);    delay(1);
    lcdWriteCommandData(0x004f,0);        //行首址0
    lcdWriteCommandData(0x004e,0);        //列首址0
    lcdWriteCommand(0x00,0x22); 
}

void lcdStartDraw(uint16_t orgX, uint16_t orgY, uint16_t cols, uint16_t rows)
{
  // use lcdWriteBus for each pixel rather than Lcd_write_data as the former doesn't set rs each time
  lcdCSLow();
  lcdAddressSet(orgX,orgY,orgX+cols-1, orgY+rows-1); // set up the box to draw in
  lcdRSHigh();
}

void lcdFinishDraw()
{
  lcdCSHigh();
}

void clearBlacklandscape()
{
   landscape();
   fastBox(0,0,320,240,0x00,0x00);
}

void portrait()
{
    isOrientationLanscape = 0;
    lcdCSLow();
    lcdWriteCommandData(0x0001,0x2B3F);
    lcdWriteCommandData(0x0011,0x6070);
    lcdWriteCommand(0x00,0x22); 
    lcdCSHigh();
}

void landscape()
{
    isOrientationLanscape = 1;
    lcdCSLow();
    lcdWriteCommandData(0x0001,0x293F);
    lcdWriteCommandData(0x0011,0x6078);
    lcdWriteCommand(0x00,0x22); 
    lcdCSHigh();
}

James Moxham

unread,
Jul 6, 2018, 10:18:45 AM7/6/18
to RC2014-Z80
Lots of little bugs to squish, but finally got Wordstar working. Needed to capture all the escape sequences and program them, and had Teraterm running in parallel to test that output looked correct. Baud rate is 19200 as there are some cheap $4 keyboard to serial converters on ebay that run at this baud rate. The green graphics mode is not quite as colourful as the pictures above, but may be more useful for displaying code and running programs. The text foreground/background can be any of the standard 16 colours. 
You can feed serial data directly into the Rx pin on the mega and have the USB connection running at the same time as there is a protection resistor in the arduino board. 
Only works with the SSD1289 tft display at the moment, though should be possible to port to other types of display. 
At the moment, not using the SD card much, but there might be some ANSI commands that could turn this into a smarter terminal, eg "DUMP filename.txt" which might be useful for transferring FAT32 files into CP/M. 
PICT0034.JPG
TouchscreenMegaNoRam_July6_2018.zip

James Moxham

unread,
Jul 10, 2018, 9:38:13 AM7/10/18
to RC2014-Z80
Screenshot and file of the very beginning of a little touchscreen keyboard for CP/M. Touch the screen and a keyboard pops up, and then enter characters. Seems to work fine, though it does need a stylus or a pen (with the nib retracted) as the keys are a little small for fingers. A minor bug at the moment, for some reason the touchscreen sometimes boots up and doesn't work. I'm working through some rather, shall we say, 'heated' discussions on the arduino forums about this :)  
Also need to draw the space bar a bit better, and the shift and control keys and decode these. I'm not sure how practical this is as the resistive touchscreens are not as responsive as the capacitative ones on iphones etc.
Back to coding! ... 
TouchscreenMegaNoRam_July10_2018.zip
PICT0042.JPG

Steve Cousins

unread,
Jul 10, 2018, 1:28:51 PM7/10/18
to RC2014-Z80
Nice project.

So is this going to be an iRC2014 ?

Steve

James Moxham

unread,
Jul 13, 2018, 10:02:50 PM7/13/18
to RC2014-Z80
Hi Steve,

Yes, good idea, maybe it could be portable! 

Lots more working with the keyboard - photo and file attached. The keypad is actually quite usable. Touch the screen anywhere and if the CP/M cursor is in the top half of the screen, it draws the keyboard in the bottom half, and vice versa. The keyboard disappears after 5 seconds or if the "Hide" key is pressed. Caps, Shift etc all working. Tab emits ascii 9. Enter emits 13. Ctrl emits ascii 1 to 26 for ctrl A-Z. The alt key could be used to bring up another screen, eg for the extended character set, for setting default colours etc. 

PICT0045.JPG
TouchscreenMegaNoRam_July14_2018.zip

James Moxham

unread,
Jul 15, 2018, 7:12:53 AM7/15/18
to RC2014-Z80
Further testing with wordstar, able to write  a document (slowly!) in Latin. Some minor updates in the code. Also a picture of the hardware I'm using with a CP/M emulation running on a Due. 

TouchscreenMegaNoRam_July15_2018.zip
PICT0058.JPG
PICT0053.jpg
Reply all
Reply to author
Forward
0 new messages