Today I more or less got the on-screen keyboard working for the MEGA65:
Not only does it appear as a nice alpha-blended composited display, it also shows which keys are being pressed, even if not being pressed on the on-screen keyboard (more on input modes in a moment):
Some might be asking why a computer with a keyboard needs to have an on-screen display in the first place. This is indeed a very good question, with several possible (if not plausible) answers:
1. If you were using a C64 keyboard instead of a C65 keyboard, you might like to press one of the additional keys.
2. If you are using a Nexys4 board, and can't remember the key mapping, you can now mash keys until you see the one you want toggle.
3. You might have a broken key, and need an emergency rescue.
4. You might be playing a game, and find it is just too inconvenient to lean forward to press a key on the keyboard, when you could instead do it from your joystick.
5. You might be using a model of the MEGA65 that completely lacks a keyboard by default, such as a tablet or phone form factor.
6. You might want to just show off when people complain that 8 bit computers can't do advanced things like composited video.
As I say, while some of those might be possible, they might not be plausible.
Now, for how this works behind the scenes.
First, this is the fourth layer of compositing that the MEGA65 supports. The other layers are:
1. Bitplaned sprite mode, which allows modifying colours of underlying objects.
2. Alpha-blended text mode, that allows pixels to shade between the foreground and background colours.
3. Matrix Mode, that displays the serial console as a composited overlay, not dissimilar to what the on-screen keyboard does.
Like Matrix Mode, the On Screen Keyboard (OSK for short) is a post-process composited display. It takes the output of the VIC-IV and Matrix Mode, and overlays the keyboard display on top. It goes on top of Matrix Mode, because you might need to drive Matrix Mode via the OSK if you don't have a real keyboard available for some reason.
Also like Matrix Mode it has its own character set ROM (currently the ASCII 8x8 font I created for the MEGA65 text editor). It also has to draw the complete keyboard layout, which is procedurally generated.
I could have done it using a bitmap instead, which would have been more flexible for the base layer, but would have also required 640x145 = ~11.3kB, unless I compressed it. More the point, it would not be possible to decide to show individual keys highlighted to show when they are being pressed.
I started out by thinking about how I could generate it procedurally. I began with the ASCII-art keyboard layout from the C65 specifications guide, and
modified it slightly to better suite my tastes:
----+ +----+----+----+----+ +----+----+----+----+ +----+----+----+----
RUN | |ESC |ALT |ASC | NO | | F1 | F3 | F5 | F7 | | F9 | F11| F13|HELP
STOP| | | |DIN |SCRL| | F2 | F4 | F6 | F8 | | F10| F12| F14|
----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----
~ | ! | " | # | $ | % | & | ' | ( | ) | { | | | |CLR |INST
_ | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | + | - |GBP |HOME|DEL
----+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+----
TAB | | | | | | | | | | | | | PI |
| Q | W | E | R | T | Y | U | I | O | P | @ | * | ^ |RESTOR
----+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+------
CTRL|SHFT| | | | | | | | | | [ | ] | } |
|LOCK| A | S | D | F | G | H | J | K | L | : | ; | = | RETURN
----+----+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+----+----+----
| | | | | | | | | < | > | ? | | |
M= | SHIFT | Z | X | C | V | B | N | M | , | . | / | SHIFT| UP|
----+-------+-+--+----+----+----+----+----+----+----+----+-+--+-+----+----+----
| SPACE | | | |
| | |LEFT|DOWN|RGHT
+--------------------------------------------+ +----+----+----
Note that I have also trimmed the left edge and right edge from the key art, and replaced some of the more exotic characters to descriptions of them. This is to keep the result to 80 columns wide (as the compositor expects 80 columns), and to fit the character set I already had (since we are still not totally sure that it is safe to use the C64 character set without a license.)
I then wrote a C programme that directly reads this ASCII form of the keyboard and creates a packed version of the key labels, ignoring all the +, - and | characters that draw the outlines of the keys, and produces a simple packed format, where multiple spaces are run-length encoded. The whole thing packs to about 400 bytes.
Then I hand-wrote the key mapping for each discrete key on each row using the keyboard matrix position numbers that the MEGA65 internally uses, numbered from $00 - $47. If a key was wide, it had $80 added to it. I probably could have figured out a way to automate the table generation, but for the small size, I figured it wasn't worth it. Also, even though I made a few mistakes initially, they were easy to find and fix by pressing keys and seeing if the correct one lit up on the screen.
This gave the following table of 7 x 16 entries:
3F,7F,47,42,50,40,7F,04,05,06,03,7F,44,45,46,43
39,38,3B,08,0B,10,13,18,1B,20,23,28,2B,30,33,00
C1,3E,09,0E,11,16,19,1E,21,26,29,2E,31,36,D1,7F
3A,0F,0A,0D,12,15,1A,1D,22,25,2A,2D,32,35,01,01
3D,8F,0C,17,14,1F,1C,27,24,2F,2C,37,B4,52,7E,7E
7E,7E,7E,3C,3C,3C,3C,3C,3C,3C,3C,3C,7E,53,07,02
7F,7F,7F,7E,7E,7E,7E,7E,7E,7E,7E,7E,7F,7E,7E,7E
The astute will note that there are only 6 rows of keys, and that the bottom row looks rather repetitive. This is because $7E is a special value that means "a non-existent key, but with a horizontal line drawn on the top edge" and $7F means "a non-existent key, with no horizontal line drawn on the top edge". This sequence draws the bottom edge on the space bar and the cursor keys in the last real row. This is also the reason for the $7F's on the first row, to leave the tops uncapped on the non-keys between the groups of keys there. If we used $7E, they would have been closed at the top.
The $C1 at the start off the third row is the TAB key, which is wide, so is really key $41 + $80 = $C1. The wide flag causes the key to be drawn 150% wide, and for the text labels to be offset by half a character, so that they don't get drawn over the vertical lines between keys.
For wider keys, like RETURN or SPACE, the same key value is simply repeated enough times to get the required width, and the logic that draws the boxes around the keys knows that this means a single longer key.
It was then a bit of fiddling to get the VHDL code working correctly to draw all this, although the end result ended up being only 400 lines. To speed up development, I wrote another little program that could be fed the output of the GHDL simulation of the OSK, and produce a PNG image of the OSK. This allowed me to find and fix bugs in a seconds instead of the almost hour it takes to synthesise the design to FPGA. Here is an example of the output of the simulation:
Here you can also see several keys being held down with the respective keys being shown in reverse video with a thin border. This was one off my goals to provide nice visual feedback of keyboard activity, and that the procedural rendering allowed without great trouble.
All in all, I am pretty happy with the result. The keyboard is clear and accurately laid out, nicely composited over the display, and yet still has a distinctively 8-bit feel to it -- and if we want to change the layout a bit, it is as easy as changing the text file that is pre-processed to produce the packed representation.
Next step will probably be to add a mechanism to have a "cursor" in the form of a highlight key that is used to navigate around the OSK, so that keys can be pressed using a joystick or other input device. This will be in addition to touch-screen support, that I hope to add in due course.
Tuesday, 15 August 2017
Sunday, 6 August 2017
Fast booting the MEGA65 with custom bitstream, kickstart and ROMs
The last couple of days I have put some more work into makingg a stream-lined software development process for the MEGA65. The goal is to make it possible to test changes to software in a few seconds, and without hassle, instead of mucking about with pulling SD cards out, flashing the SQI flash on the FPGA boards and generally forgetting what it was you were trying by the time you got your modified software loaded.
An additional motivation for this is that the SD card interface on one of our hand-modified prototypes is not working at the moment, and Falk needed another way to get bitstreams, Kickstart firmware, C65 ROMs and software he is writing onto the machine easily.
This was a new requirement, that required something more advanced than the monitor_load utility that I wrote last week to solve some of these problems.
Specifically, it needed to be posssible to load a C65 ROM and character ROM image, without ever even initialising the SD card.
So I set about modifying monitor_load to load the ROMs into the correct memory location. That was fairly easy, apart from a little speed bump caused by the limitation of the bulk memory upload command in the serial monitor. That problem is that the address counter when loading only increments the bottom 16 bits of the address, combined with the start address needing to be one less than the first address.
For example, to load memory to pre-load $20000-$2FFFF, i.e., the first 64KB of a C65 ROM, we couldn't just subtract one from the address, and say l1ffff 2ffff, because it would only increment the bottom 16 bits, and leave the "1" at the front of the address the same. (The "l" in front of the address is the command code to tell the serial monitor to bulk load memory.)
Instead, we have to say l2ffff 2ffff: 1 is added automatically, but only to the bottom 16 bits which rotate over from $FFFF to $0000, leaving the leading "2" unchanged, for a complete address of $20000 -- exactly what we want.
The next challenge was how to tell Kickstart not to initialise the SD card, but instead to just launch the loaded ROM. My simple solution to this problem was to add two consecutive instructions just before SD card initialisation would occur:
BIT go64
BIT $1234
where go64 is the label in the assembly language of the routine to launch the loaded ROM. The monitor_load program searches for this signature, and changes the first BIT instruction into a JMP, so that it becomes JMP go64, thus exiting to the loaded ROM, without worrying about the SD card.
With this change in place, there is really very little for Kickstart to do, and it does it so quickly at 50MHz, that you don't even see the MEGA65 kickstart screen, before it drops to C65 mode, as can be seen in the following video:
What is also really nice is that the whole process takes only a few seconds. You can see that the FPGA fires up in a couple of seconds. Much of the rest of the time is waiting for the monitor to wake up from sleep.
Combining this with the existing ability of monitor_load to load and automatically run a program in C64 mode (and C65 mode would not be hard to add), it is possible to execute a single command that loads the bitstream, kickstart, C65 ROM and program of choice, and sets it running -- all in less than 10 seconds, as can be seen in this video:
As usual, the curious can checkout the source code on github.
(Also, for the curious, the strange program that runs in this video is an old test of the hardware-accelerated proportional text mode that the MEGA65 has. This little program takes a UTF-8 text file, and renders the variable width glyphs in text mode, which makes it both fast, and very memory efficient, as repeating the same character re-uses the glyph memory.)
For Falk and the machine without a working SD card, the next challenge is to provide remote control of the floppy controller, so that D81 disk images can be used, without having to load them on the (in his case, not working) SD card.
The ability to automatically trap to the hypervisor already exists, and it is now a case of writing the trap code in Kickstart, and modifying monitor_load to interface to it, so that a disk image can also be specified when starting the machine, and knowning that all disk access will be redirected to it.
With that in place, the ongoing development of the MEGA65 version of GEOS will hopefully be able to proceed very quickly, with no inserting of SD cards required.
And it shouldn't take too much effort to make the disk virtualisation code, because we already have the tools to iterate on the Kickstart firmware very quickly, through monitor_load itself.
Tuesday, 1 August 2017
Getting 1080p 50Hz working ... using a video mode editor written in BASIC v2
One of the joys of the MEGA65 project is that it is all about doing something that is not grounded in conventional measures of wisdom or practice -- at least none invented since the 1980s.
One of the TODO items for a while now has been to get 1080p at 50Hz (for PAL) and 60Hz (for NTSC) video modes working, ready for the move to HDMI on the new MEGA65 mother board.
This has been a bit of a drawn out process, partly because of everything else I have going on, and partly because I didn't have the tools to quickly and easily test and move forward. That latter problem has now been substantially improved on several fronts:
1. The monitor_load program makes it easy to try a new bitstream and/or Hypervisor ROM on the MEGA65, without having to fiddle about with SD cards.
2. I now have a native Linux machine, so that I don't have to muck about with transferring bitstreams and source back and forth in and out of a virtual machine on my mac. It also means that synthesis is a bit faster, without the overhead of the virtual machine.
Together, those two things, while not particularly ground shaking, have made a huge difference to what I can achieve in the little puddles of time I have.
The next step today was to implement a monitor_save program, that lets me save whatever is loaded in C64 mode, even if the program is running. This isn't a freeze function, but rather just saving BASIC program memory. This makes it easy to work on a BASIC program on the MEGA65, saving it as I go along.
So now I had the means to save and load a program from my Linux box from and onto the MEGA65 in a second or two, as well as build and try out new bitstreams quickly, thus allowing me to do even more in the limited time available to me.
Back to 1080p video modes, I have worked over the past week to make VIC-IV registers at $D072-$D07C that allow complete control over the VGA video signal generation, so that I could try out various mode lines, with a view to generating the 1080p modes.
I also found out by accident that one of the VGA monitors at work is totally happy to do very low frame rates, down to and below 50Hz.
Now I was set, I had the tools to allow me to write a simple program to try out and modify video parameters on the MEGA65, to tweak them for proper video image placement and timing.
One of the joys of the C64, is that it contains a powerful and simple programming language out of the box, i.e., BASIC. While BASIC v2 is a bit minimal, it is totally functional, so I started hacking away on an interactive video mode line explorer.
Within an hour or so, I had not only a functional video mode editor, but had also worked out the correct parameters for 1080p 50Hz, 1080p 60Hz, and 1200p 60Hz, all using a fixed 150MHz pixel clock. Here are some screen shots of my program in the various modes, and as I was testing them on the monitor:
First we have 1080p @ 60Hz. The BASIC program calculates a rough estimate of the horizontal and vertical frequencies of the mode. The letters and numbers in brackets let you adjust the value to the left by -10, -1, +1 and +10 respectively. If you look carefully you can see the bit of letter-boxing, because this monitor is actually nativelly 1200p.
Then a ~50Hz mode as I was trying to figure out a good 50Hz mode, and checking what the monitor thought of the mode. This monitor, while nice for such funny modes, is a pain to get it to show the current mode. You have to navigate through quite a few menus to see the current mode info.
And 1920x1200 @ 60-ish Hz.
In that mode in particular we can see that the scaling of the video imag is not correct within the borders. This is one of the next things on the list to fix. It isn't hard, as the VIC-IV already has the necessary scaling registers.
Meanwhile, for the curious, here is the BASIC listing of the program I wrote to let me tweak and fiddle with the video modes, as output using petcat -2
10 k=53295
20 pokek,asc("g")
30 pokek,asc("s")
40 poke0,65
50 r0=53248+7*16+2
60 poke650,128
70 poke53280,6:poke53281,11
100 rem default mode values
110 ss=2290:se=100
120 fh=1072:dh=1056
130 fw=2432:dw=1920
140 fp=128
1000 printchr$(147);"{wht}mega65 video mode editor"
1010 print
1020 print"hsync start=";ss;" (a,s,d,f)"
1030 print"hsync end=";se;" (q,w,e,r)"
1040 print"front porch=";fp;" (z,x,c,v)"
1050 print"frame width=";fw;" (t,y,u,i)"
1060 print"display width=";dw;" (g,h,j,k)"
1070 print"frame height=";fh;" (1,2,3,4)"
1080 print"display height=";dh;" (5,6,7,8)"
1900 print"hfreq = ";150000/fw;"khz"
1910 print"vfreq = ";150000000/fw/fh;"hz"
2000 poker0+1,se/256
2010 poker0+2,seand255
2020 poker0+10,ss/256
2030 poker0+9,ssand255
2040 poker0+0,fp
2050 poker0+3,dwand255
2060 poker0+4,fwand255
2070 poker0+5,int(dw/256)+16*int(fw/256)
2080 poker0+6,dhand255
2090 poker0+7,fhand255
2100 poker0+8,int(dh/256)+16*int(fh/256)
3000 geta$:ifa$=""goto3000
3005 printa$
3010 ifa$="q"thense=se-10
3020 ifa$="w"thense=se-1
3030 ifa$="e"thense=se+1
3040 ifa$="r"thense=se+10
3050 ifa$="a"thenss=ss-10
3060 ifa$="s"thenss=ss-1
3070 ifa$="d"thenss=ss+1
3080 ifa$="f"thenss=ss+10
3090 ifa$="z"thenfp=fp-10
3100 ifa$="x"thenfp=fp-1
3110 ifa$="c"thenfp=fp+1
3120 ifa$="v"thenfp=fp+10
3130 ifa$="t"thenfw=fw-10
3140 ifa$="y"thenfw=fw-1
3150 ifa$="u"thenfw=fw+1
3160 ifa$="i"thenfw=fw+10
3170 ifa$="1"thenfh=fh-10
3180 ifa$="2"thenfh=fh-1
3190 ifa$="3"thenfh=fh+1
3200 ifa$="4"thenfh=fh+10
3210 ifa$="5"thendh=dh-10
3220 ifa$="6"thendh=dh-1
3230 ifa$="7"thendh=dh+1
3240 ifa$="8"thendh=dh+10
3500 ifss<0thenss=2999
3510 ifse<0thense=2999
3520 iffp<0thenfp=255
3530 iffw<dwthenfp=dw+1000
3540 ifdw<640thendw=1920
3800 ifss>2999thenss=0
3810 ifse>2999thense=0
3820 iffp>255 thenfp=0
3830 iffw>3000thenfw=dw+50
3840 ifdw>1920thendw=640
3850 iffw<ssthenss=fw-10
3860 iffh<480thenfh=1500
3870 ifdh<480thendh=fh-10
3880 iffh<dhthenfh=dh+2
3890 ifdh>1300thendh=480
3900 iffh>1300thenfh=480
4000 goto1000
One of the TODO items for a while now has been to get 1080p at 50Hz (for PAL) and 60Hz (for NTSC) video modes working, ready for the move to HDMI on the new MEGA65 mother board.
This has been a bit of a drawn out process, partly because of everything else I have going on, and partly because I didn't have the tools to quickly and easily test and move forward. That latter problem has now been substantially improved on several fronts:
1. The monitor_load program makes it easy to try a new bitstream and/or Hypervisor ROM on the MEGA65, without having to fiddle about with SD cards.
2. I now have a native Linux machine, so that I don't have to muck about with transferring bitstreams and source back and forth in and out of a virtual machine on my mac. It also means that synthesis is a bit faster, without the overhead of the virtual machine.
Together, those two things, while not particularly ground shaking, have made a huge difference to what I can achieve in the little puddles of time I have.
The next step today was to implement a monitor_save program, that lets me save whatever is loaded in C64 mode, even if the program is running. This isn't a freeze function, but rather just saving BASIC program memory. This makes it easy to work on a BASIC program on the MEGA65, saving it as I go along.
So now I had the means to save and load a program from my Linux box from and onto the MEGA65 in a second or two, as well as build and try out new bitstreams quickly, thus allowing me to do even more in the limited time available to me.
Back to 1080p video modes, I have worked over the past week to make VIC-IV registers at $D072-$D07C that allow complete control over the VGA video signal generation, so that I could try out various mode lines, with a view to generating the 1080p modes.
I also found out by accident that one of the VGA monitors at work is totally happy to do very low frame rates, down to and below 50Hz.
Now I was set, I had the tools to allow me to write a simple program to try out and modify video parameters on the MEGA65, to tweak them for proper video image placement and timing.
One of the joys of the C64, is that it contains a powerful and simple programming language out of the box, i.e., BASIC. While BASIC v2 is a bit minimal, it is totally functional, so I started hacking away on an interactive video mode line explorer.
Within an hour or so, I had not only a functional video mode editor, but had also worked out the correct parameters for 1080p 50Hz, 1080p 60Hz, and 1200p 60Hz, all using a fixed 150MHz pixel clock. Here are some screen shots of my program in the various modes, and as I was testing them on the monitor:
First we have 1080p @ 60Hz. The BASIC program calculates a rough estimate of the horizontal and vertical frequencies of the mode. The letters and numbers in brackets let you adjust the value to the left by -10, -1, +1 and +10 respectively. If you look carefully you can see the bit of letter-boxing, because this monitor is actually nativelly 1200p.
Then a ~50Hz mode as I was trying to figure out a good 50Hz mode, and checking what the monitor thought of the mode. This monitor, while nice for such funny modes, is a pain to get it to show the current mode. You have to navigate through quite a few menus to see the current mode info.
And 1920x1200 @ 60-ish Hz.
In that mode in particular we can see that the scaling of the video imag is not correct within the borders. This is one of the next things on the list to fix. It isn't hard, as the VIC-IV already has the necessary scaling registers.
Meanwhile, for the curious, here is the BASIC listing of the program I wrote to let me tweak and fiddle with the video modes, as output using petcat -2
10 k=53295
20 pokek,asc("g")
30 pokek,asc("s")
40 poke0,65
50 r0=53248+7*16+2
60 poke650,128
70 poke53280,6:poke53281,11
100 rem default mode values
110 ss=2290:se=100
120 fh=1072:dh=1056
130 fw=2432:dw=1920
140 fp=128
1000 printchr$(147);"{wht}mega65 video mode editor"
1010 print
1020 print"hsync start=";ss;" (a,s,d,f)"
1030 print"hsync end=";se;" (q,w,e,r)"
1040 print"front porch=";fp;" (z,x,c,v)"
1050 print"frame width=";fw;" (t,y,u,i)"
1060 print"display width=";dw;" (g,h,j,k)"
1070 print"frame height=";fh;" (1,2,3,4)"
1080 print"display height=";dh;" (5,6,7,8)"
1900 print"hfreq = ";150000/fw;"khz"
1910 print"vfreq = ";150000000/fw/fh;"hz"
2000 poker0+1,se/256
2010 poker0+2,seand255
2020 poker0+10,ss/256
2030 poker0+9,ssand255
2040 poker0+0,fp
2050 poker0+3,dwand255
2060 poker0+4,fwand255
2070 poker0+5,int(dw/256)+16*int(fw/256)
2080 poker0+6,dhand255
2090 poker0+7,fhand255
2100 poker0+8,int(dh/256)+16*int(fh/256)
3000 geta$:ifa$=""goto3000
3005 printa$
3010 ifa$="q"thense=se-10
3020 ifa$="w"thense=se-1
3030 ifa$="e"thense=se+1
3040 ifa$="r"thense=se+10
3050 ifa$="a"thenss=ss-10
3060 ifa$="s"thenss=ss-1
3070 ifa$="d"thenss=ss+1
3080 ifa$="f"thenss=ss+10
3090 ifa$="z"thenfp=fp-10
3100 ifa$="x"thenfp=fp-1
3110 ifa$="c"thenfp=fp+1
3120 ifa$="v"thenfp=fp+10
3130 ifa$="t"thenfw=fw-10
3140 ifa$="y"thenfw=fw-1
3150 ifa$="u"thenfw=fw+1
3160 ifa$="i"thenfw=fw+10
3170 ifa$="1"thenfh=fh-10
3180 ifa$="2"thenfh=fh-1
3190 ifa$="3"thenfh=fh+1
3200 ifa$="4"thenfh=fh+10
3210 ifa$="5"thendh=dh-10
3220 ifa$="6"thendh=dh-1
3230 ifa$="7"thendh=dh+1
3240 ifa$="8"thendh=dh+10
3500 ifss<0thenss=2999
3510 ifse<0thense=2999
3520 iffp<0thenfp=255
3530 iffw<dwthenfp=dw+1000
3540 ifdw<640thendw=1920
3800 ifss>2999thenss=0
3810 ifse>2999thense=0
3820 iffp>255 thenfp=0
3830 iffw>3000thenfw=dw+50
3840 ifdw>1920thendw=640
3850 iffw<ssthenss=fw-10
3860 iffh<480thenfh=1500
3870 ifdh<480thendh=fh-10
3880 iffh<dhthenfh=dh+2
3890 ifdh>1300thendh=480
3900 iffh>1300thenfh=480
4000 goto1000
Monday, 31 July 2017
Revamping Hypervisor boot display, and SPACE to enter utility menu
Now that I have a much easier way to develop the boot ROM for the MEGA65 via the monitor_load command (which I have now pushed up from 230,400bps to 2,000,000bps as I previously discussed), I got inspired to fix the boot display of the MEGA65.
Basically in the past we had a 64x64 area for a 256-colour logo. This predated the renaming to the MEGA65, and the creation of the wide MEGA65 banner. As a result the banner was all squished into a tiny space and was almost unreadable and quite ugly.
I'd been meaning for a while to rework the boot ROM to support a 320 pixel wide banner instead, so that the MEGA65 logo could be properly displayed. So this is what I have done. I have also gone a step further, and included the MEGA65 logo as preinitialised data in RAM, so that it still shows up, even if you don't have an SD card inserted.
In the process, because it is now so quick and easy to test new versions of the boot ROM, I also added the option to hold SPACE to enter the utility menu, which serves a similar role to the BIOS menu on old PCs, but will have different utilities. The main utility planned for now is a combined FDISK+FORMAT utility, to make it easier to setup a new SD card for use in the MEGA65. The utilities are also stored in pre-initialised memory (in this case the upper 30KB of the 32KB colour RAM), so that you don't need an SD card or anything else for them to be there.
We have the bulk of the FDISK+FORMAT utility already written, but need to work out how to get CC65 compiled programs to run on the MEGA65 when there is no C64 ROM yet loaded.
But for now, here is a screen shot of the revamped boot display, looking, I think, much nicer:
Hope you enjoy it.
Basically in the past we had a 64x64 area for a 256-colour logo. This predated the renaming to the MEGA65, and the creation of the wide MEGA65 banner. As a result the banner was all squished into a tiny space and was almost unreadable and quite ugly.
I'd been meaning for a while to rework the boot ROM to support a 320 pixel wide banner instead, so that the MEGA65 logo could be properly displayed. So this is what I have done. I have also gone a step further, and included the MEGA65 logo as preinitialised data in RAM, so that it still shows up, even if you don't have an SD card inserted.
In the process, because it is now so quick and easy to test new versions of the boot ROM, I also added the option to hold SPACE to enter the utility menu, which serves a similar role to the BIOS menu on old PCs, but will have different utilities. The main utility planned for now is a combined FDISK+FORMAT utility, to make it easier to setup a new SD card for use in the MEGA65. The utilities are also stored in pre-initialised memory (in this case the upper 30KB of the 32KB colour RAM), so that you don't need an SD card or anything else for them to be there.
We have the bulk of the FDISK+FORMAT utility already written, but need to work out how to get CC65 compiled programs to run on the MEGA65 when there is no C64 ROM yet loaded.
But for now, here is a screen shot of the revamped boot display, looking, I think, much nicer:
Hope you enjoy it.
Thursday, 27 July 2017
Fast-loading via serial monitor for development (part 2)
I woke up in the middle of the night, so decided to finish the serial monitor fast loader for supporting development.
After a bit of fiddling, it is now possible to compile and use the monitor_load program to:
1. Load a fresh bitstream and completely reset the MEGA65, thus allowing reloading a program regardless of the state of the machine.
2. Wait until the M65 boots to C65 mode.
3. Switch to C64 mode via GO64
4. As soon as it is in C64 mode, load the program you provide on the command line.
Example command line:
tools/monitor_load /dev/ttyUSB1 something.prg nexys4ddr.bit
As the serial monitor interface runs at 230Kbps, this gives a maximum load speed of around 20KB/sec. At the moment it is probably around 15KB/sec, so quite acceptable.
From typing the command to having the program completely loaded takes about 10.5 seconds, for a 16KB program. That is, about 9.5 seconds is spent loading the bitstream, and waiting for Kickstart to prepare the SD card, load the C65 ROM etc, and get to the C65 prompt.
After a bit of fiddling, it is now possible to compile and use the monitor_load program to:
1. Load a fresh bitstream and completely reset the MEGA65, thus allowing reloading a program regardless of the state of the machine.
2. Wait until the M65 boots to C65 mode.
3. Switch to C64 mode via GO64
4. As soon as it is in C64 mode, load the program you provide on the command line.
Example command line:
tools/monitor_load /dev/ttyUSB1 something.prg nexys4ddr.bit
As the serial monitor interface runs at 230Kbps, this gives a maximum load speed of around 20KB/sec. At the moment it is probably around 15KB/sec, so quite acceptable.
From typing the command to having the program completely loaded takes about 10.5 seconds, for a 16KB program. That is, about 9.5 seconds is spent loading the bitstream, and waiting for Kickstart to prepare the SD card, load the C65 ROM etc, and get to the C65 prompt.
Monday, 24 July 2017
Fast-loading via serial monitor for development (part 1)
Ages back I started working on a mechanism to allow fast loading of programs via the serial monitor interface, but never finished it.
The idea was to add a command to the serial monitor interface that allowed bulk up-loading of data into memory, and trapping the LOAD vector so that it triggered this mechanism. Funnily enough, trapping LOAD from the serial monitor, working out which program to load, and loading it was the easy part. This has been in monitor_load.c for some time now.
The hard part was working out why what should have been a very simple memory upload command wasn't working.
Well, I finally figured out the problem with this command last night, and fixed it. The problem, as is so often the case, turned out to be quite simple: There was a safety catch that reset the UART monitor to CPU request strobe whenever a character was received via the UART interface. This is normally fine, but in bulk upload, this was cancelling the request to write the byte to memory each and every time it was made, resulting in timeout errors in the UART monitor, and a complete lack of loading of the data.
So I fixed this problem, and now I can easily write ranges of memory with arbitrary via the UART interface, at approximately 20KB/sec, since I am running the serial interface at 230,400bps.
The nice thing is that I also worked out how to jtag program the FPGA via the USB lead which also carries the serial monitor interface. This means that I can write a small shell script that pushes a bitstream into the FPGA and resets the machine, and then waits for someone to try to LOAD something, and then loads what you want at 20KB/sec. This is a really nice advance for writing software for the MEGA65, as from a cross-compiler you will be able to start the program automatically on a clean machine in just a few seconds. If nothing else, it means that you won't have to fiddle about pulling microSD cards out any more.
You might have noticed I used the future-tense there. This is because while I now have all the pieces mostly ready, I haven't finished pulling them together. I hope to do this over the next few evenings, time and energy permitting.
What I have managed to do, however, is to make the serial interface speed run-time selectable from the serial monitor itself. This means that we don't have to be limited to 20KB/sec, which while nice, would still take a few seconds to load 64KB, and a rather annoying dozen seconds to load 256KB (128KB normal RAM, plus 128KB of "ROM" RAM), when testing larger programs.
There isn't too much to see at the moment, except if you were to try my new bitstream and issue the command:
+32
from the UART monitor interface. At that point you would see rubbish, until you set your terminal program to 1,000,000bps, i.e., a little better than four times the current speed, and thus allowing something like 80KB - 100KB/sec, which should allow for nice fast loading of all of memory.
So then I tried:
+18
to set it to 2,000,000bps. That seems to work, too, and should allow ~160KB - 200KB/seconds. Even nicer. Sadly +10 didn't work for trying to set it to 3,000,000bps.
Oh well.
Anyway, hopefully I will have an update in a few days showing the ability to fast-load close to 200KB/sec in a development environment, to make writing MEGA65 software more pleasant to do.
The idea was to add a command to the serial monitor interface that allowed bulk up-loading of data into memory, and trapping the LOAD vector so that it triggered this mechanism. Funnily enough, trapping LOAD from the serial monitor, working out which program to load, and loading it was the easy part. This has been in monitor_load.c for some time now.
The hard part was working out why what should have been a very simple memory upload command wasn't working.
Well, I finally figured out the problem with this command last night, and fixed it. The problem, as is so often the case, turned out to be quite simple: There was a safety catch that reset the UART monitor to CPU request strobe whenever a character was received via the UART interface. This is normally fine, but in bulk upload, this was cancelling the request to write the byte to memory each and every time it was made, resulting in timeout errors in the UART monitor, and a complete lack of loading of the data.
So I fixed this problem, and now I can easily write ranges of memory with arbitrary via the UART interface, at approximately 20KB/sec, since I am running the serial interface at 230,400bps.
The nice thing is that I also worked out how to jtag program the FPGA via the USB lead which also carries the serial monitor interface. This means that I can write a small shell script that pushes a bitstream into the FPGA and resets the machine, and then waits for someone to try to LOAD something, and then loads what you want at 20KB/sec. This is a really nice advance for writing software for the MEGA65, as from a cross-compiler you will be able to start the program automatically on a clean machine in just a few seconds. If nothing else, it means that you won't have to fiddle about pulling microSD cards out any more.
You might have noticed I used the future-tense there. This is because while I now have all the pieces mostly ready, I haven't finished pulling them together. I hope to do this over the next few evenings, time and energy permitting.
What I have managed to do, however, is to make the serial interface speed run-time selectable from the serial monitor itself. This means that we don't have to be limited to 20KB/sec, which while nice, would still take a few seconds to load 64KB, and a rather annoying dozen seconds to load 256KB (128KB normal RAM, plus 128KB of "ROM" RAM), when testing larger programs.
There isn't too much to see at the moment, except if you were to try my new bitstream and issue the command:
+32
from the UART monitor interface. At that point you would see rubbish, until you set your terminal program to 1,000,000bps, i.e., a little better than four times the current speed, and thus allowing something like 80KB - 100KB/sec, which should allow for nice fast loading of all of memory.
So then I tried:
+18
to set it to 2,000,000bps. That seems to work, too, and should allow ~160KB - 200KB/seconds. Even nicer. Sadly +10 didn't work for trying to set it to 3,000,000bps.
Oh well.
Anyway, hopefully I will have an update in a few days showing the ability to fast-load close to 200KB/sec in a development environment, to make writing MEGA65 software more pleasant to do.
Tuesday, 6 June 2017
Building lab-prototype MEGA65, and remembering the thrill of my first C65
After getting the MEGA65 prototype PCB up and running last night, today was time to build up the prototype in the lab.
Second, make sure that it boots fine:
Third, get my Commodore 65 keyboard that I bought ages back on ebay, and one of the plastic laser-cut outlines I made when I was starting to work on the laptop concept for the MEGA65:
Work out how I was going to hold it in place. There are three hole-throughs on the keyboard:
Looking closer at one of them:
Unfortunately, one of them is behind the space bar (which is possibly the widest space bar I have ever seen on a keyboard -- a point which is causing us some fun in getting our own production in order for our own MEGA65 keyboards.) So I resorted to drilling some holes in my acrylic outside, and screwing a retainer strip on the back. It isn't perfect, but it works enough for now:
You can also see that I have screwed the C65 prototype motherboard down to another panel, and then added a home-made friction hinge (although it isn't strong enough to hold the keyboard open in position), so that I can open it up to get to the SD card. We might yet extend the SD card to a better location, so that we don't need to open the "lid" all the time.
Putting it altogether and powering it up, it still looks very, very rough -- but the point is we now have a working and usable bench-top prototype, from which to progress.
And looking in the side, where you can really see that the temporary physical construction is indeed a gross hack.
So, now I have it working. One of the really unexpected things was a wave of emotion and nostalgia as I started interacting with a C65 via a real feeling keyboard for the first time in close to ten years. I didn't get this when using a keyrah and Commodore 64 keyboard on it, and certainly not using a USB PC keyboard.
But suddenly with a real C65 keyboard, it felt like I was 19 again, and using the prototype C65 again. It's hard to explain. It might be the tactile feel of the keyboard, or even the subtle timing of where in the key press the computer registers the input, or some combination of the two. But whatever the trigger, it was like smelling a familiar smell for the first time in years, and having that rush of memory and recollection, including evoking the emotion of the moment, not just the cerebral memory of it.
It is this thrill and experience that I hope we can share as we continue with making new C65s through the MEGA65 project. That wonder of discovering a new heir in a noble lineage of computers. We might not be Commodore, but I am convinced that we will be able to bring the C65 to completion, and finally bring the last chapter of the 8-bit dynasty to life.
Subscribe to:
Posts (Atom)





