Saturday, 2 March 2019

Auto-Detecting Required Revision of DMAgic Chip, improving default audio mixer settings

In the last hour or two before I fly home from Germany, we decided to tackle a couple of little things to make the system easier to use:

The Commodore 65 prototypes have one of two different revisions of the DMAgic DMA chip, which are not entirely compatible with one another, because the format of the DMA lists differs.  The revision B list has an extra sub-command byte between the destination bank and modulo bytes, as these example lists show:

        ; F018A DMA list
        .byte $04   ; COPY + chained request
        .word 1996  ; 40x25x2-4 = 1996
        .word $0400 ; copy from start of screen at $0400
        .byte $00   ; source bank 00
        .word $0404 ; ... to screen at $0402
        .byte $00   ; screen is in bank $00
        .word $0000 ; modulo (unused)





        ; F018B DMA list
        .byte $04   ; COPY + chained request
        .word 1996  ; 40x25x2-4 = 1996
        .word $0400 ; copy from start of screen at $0400
        .byte $00   ; source bank 00
        .word $0404 ; ... to screen at $0402
        .byte $00   ; screen is in bank $00

        .byte $00   ; F018B sub-command
        .word $0000 ; modulo (unused)



Basically having the wrong mode makes MEGA65 BASIC do all sorts of odd things, like produce the delightful ? PROGRAM MANGLED  ERROR.  We should try to avoid those, so it would be great for the boot ROM to automatically recognise when a C65 ROM is loaded, and to know which DMAgic revision the ROM needs.

Fortunately, this is fairly easy to do, because at offset $16 in the C65 ROM there is a string like "V910111" that indicates the date of the ROM.  So we can just check for the V there, an then test the date.  If it isn't a C65 ROM, then it doesn't matter which DMAgic mode we use, so there is no problem from false positives.  Then all we need to know, is from which date the new DMAgic was required, and that turns out to be from V910523, so a little bit of code to test the date, like the following is called for:

syspart_dmagic_autoset:
        ; Set DMAgic revision based on ROM version
        ; $20017-$2001D = "V9xxxxx" version string.
        ; If it is 900000 - 910522, then DMAgic revA, else revB
        lda #$16
        sta zptempv32
        lda #$00
        sta zptempv32+1
        sta zptempv32+3   
        lda #$02
        sta zptempv32+2
        ldz #$00
        nop
        lda (<zptempv32),z
        cmp #$56
        beq @hasC65ROMVersion
        rts
@hasC65ROMVersion:
        ; Check first digit is 9
        inz
        nop
        lda (<zptempv32),z
        cmp #$39
        bne @useDMAgicRevB
        ; check if second digit is 0, if so, revA
        inz
        nop
        lda (<zptempv32),z
        cmp #$30
        beq @useDMAgicRevA
        ; check if second digit != 1, if so, revB
        cmp #$31
        bne @useDMAgicRevB
        ; check 3rd digit is 0, if not, revB
        inz
        nop
        lda (<zptempv32),z
        cmp #$30
        bne @useDMAgicRevB
        ; check 4th digit is >5, if so, revB
        inz
        nop
        lda (<zptempv32),z
        cmp #$36
        bcs @useDMAgicRevB
        ; check 4th digit is <5, if so, revA
        cmp #$35
        bcc @useDMAgicRevA
        ; check 5th digit <=> 2
        inz
        nop
        lda (<zptempv32),z
        cmp #$32
        bcc @useDMAgicRevA
        cmp #$33
        bcs @useDMAgicRevB
        ; check 6th digit <3
        inz
        nop
        lda (<zptempv32),z
        cmp #$33
        bcc @useDMAgicRevA
@useDMAgicRevB:
        ldz #$00
        lda #$01
        tsb $d703

        ldx #<msg_dmagicb
        ldy #>msg_dmagicb
        jmp printmessage

@useDMAgicRevA:
        ldz #$00
        lda #$01
        trb $d703
       
        ldx #<msg_dmagica
        ldy #>msg_dmagica
        jmp printmessage

And then the boot ROM can now automatically work out the correct DMAgic version, and tells you at boot time which it has selected, as can be seen in the messages below:


While we were fiddling with that, we also decided to improve the default audio-mixer settings, so that the microphones are not connected to the line out by default, but are for the cellular modems, and generally improve the audio line levels for the SIDs.  The output volume is now much better, and it all sounds nice and clear and loud.







Multiple Freeze Slots

Recently we were excited to be able to begin to show-off the freeze menu of the MEGA65, but at that time we had only one freeze slot working.

So I have spent some time this week while with the MEGA65 team here in Germany to figure out what was going wrong, and how to fix it.

The problem basically was that we were not calculating the address on the SD card of the freeze slots correctly, and then were passing the 16-bit slot number with high and low bytes swapped around.  All quite annoying, but nice little bugs that could be solved without wasting lots of time resynthesising multiple times.

The result is now as it should be: We can freeze a program, choose whichever slot to save it in, and then load it back up as often as you want later on.  So quite quickly we had frozen a few games and even a MEGA65 demo, which we can then easily flick through.

So here are a couple of short videos of using the freeze menu to access various things saved in different freeze slots.

You can play spot the differences between the thumbnail images.  Because we are in Germany, the top version of the video is in German, and the lower one is in English for those of you who are unable to understand Australo-deutsch ;)





Also, here are some screenshots of the freeze menu looking at some of the different slots with things saved in them.  I continue to be very happy that I implemented the hardware thumbnail generator, so that it is relatively easily to see what is saved in a slot. We will add the ability to name the slots, search for them, jump to specific slot numbers by typing the numbers etc, once we get a bit of spare time.




And here is how a slot with nothing saved in it can look:


Audio Mixer in Freeze Menu and Fixing SID Problems

The audio cross bar switch that we have implemented is a delight, allowing tuning of the input levels of all audio sources, as well as control of master output levels.  But until now, there has been no way for a user to easily control the audio levels. This was a bit of a pain, as the microphone input on the Nexys boards is by default active, and thus as we have worked to work out the source of some bugs in the SIDs, having feedback via the microphones was, shall we say, rather unhelpful.

Thus I finally got around to making a control interface for the audio cross-bar switch.  This has been built into the freeze menu to make it easy to change the audio levels when running a program, without having the program to know about the cross-bar.  The first step was to add an "A" option to go to the audio mixer in the freeze menu.  "A" was used for enabling cartridges, so that function has been changed to "T".


This then takes you to a screen like this, where you can modify all the coefficients for the cross bar:



This looks quite complicated, but is in reality not too bad.  The columns of 4-digit hex numbers (we will eventually make a friendlier display of the volume levels) are the level for the input on the left for the output at the top.  There is also a pseudo input which is the master volume input. The other inputs down the left, from top to bottom are the left SID, right SID, first and second phone modems (for the MEGAphone, which supports dual cellular radios), bluetooth left and right microphone/audio inputs (again for the MEGAphone), line in left and right, the left and right 16-bit digi channels of the MEGA65, then up to four microphone channels (again, mostly for the MEGAphone), then one input channel that is spare, and the master volume level.

The output channels are left and right speaker output, then outputs for the two phone radios, stereo output for bluetooth, and finally wired head-phones stereo channels.  For the desktop version we can of course remove the majority of these from the menu, and make it a lot friendlier, the main thing for now is that we have a facility that works, and that we can improve upon.

So, finally we were able to start investigating what was wrong with the SIDs.  We have known for a while that some things sound quite wrong with the new VHDL SID implementation we are using, despite the fact that technically, it should sounds really great, with all internal features of the SIDs implemented carefully by the author.  For example, the Trap demo shown below, had very muffled drums, and just generally sounded wrong:

 I'm not very musically inclined, so couldn't alone even work out what was wrong.  But this week I am not working alone, but rather with the MEGA65 crew here in Germany, so together with Deft and Libi we started investigating. After about an hour of fiddling and comparing audio output from the VICE with the output from the MEGA65 (with the microphone input on the MEGA65 nicely muted using the audio mixer interface in the freeze menu), we realised that the problem was actually quite simple: The SID was producing audio one octave too low, and the ADSR behaviour was also half-speed.  Thus it seemed that the frequency input to the audio engines of the SIDs needed doubling.

After months of worrying about how hard the problem would be to find, and then to fix by fiddling with low-level signal processing algorithms in the SID implementation, it ended up taking only about a further hour to fix.

You can hear the difference between the old broken audio, and the new fixed audio. (The lower wave form in each video is the old broken audio, and the upper waveform is the fixed one, for those wanting to interpret the images in the videos)




The difference is noticeable in all sorts of games, and it really does now sound simply great.  This is the joy of the power of open-source projects -- thanks to the SID work of Alvaro Lopes (SID filters in VHDL) and Jan Derogee (SID VHDL implementation), the MEGA65 now has really, really nice sound.



Towards Dual SD-Card Support

The MEGA65 was intended from the outset to support multiple SD Cards / storage devices, and there is considerable provision made for this in our boot ROM, if not actual current support.  This takes the form of allowing multiple drives, and for each drive to indicate which storage device it has come from.

Full active support is still a while off, but what we have done today is to add support for two SD cards, and to have the boot ROM work out which one has an SD Card inserted.  This will get used in the R2 PCBs that are being designed at the moment.  But the pressing reason for this was to get the R1 PCB that Falk is using to develop GEOS back working, as a couple of FPGA pins have died on it that were responsible for the SD card interface.  We have rerouted a couple of unused pins that connect to the HDMI controller to get a physical connection:


I have then also modified the SD controller so that it has a multiplexer to select which of two SD Card busses is active at any point in time.  This is controlled in software by writing $C0 (for Card 0) or $C1 (for Card 1) to $D680, the SD Card command register.  This turned out to be more of a pain than it should have been, because things kept going strange for no apparent reason.  I had to refactor the multiplexer a couple of times until it was working reliably, even though the problems, as far as I can see, were nothing to do with the SD card interface.

This kind of thing happens more often than I would like when working with VHDL. I am sure some of the problems are subtle (or not so subtle) things that I have done wrong, but others seem to defy explanation.  This was one of those: I added simply a multiplexer for the SD card busses, and suddenly the MEGA65 had keyboard problems.

Anyway, after some considerable effort, we managed to get it mostly working, but then suddenly the keyboard stopped working at 40MHz again -- a problem we have seen before. But then after doing some other unrelated fixes to the SID, suddenly the keyboard is again working at 40MHz.  Hardware is annoying, sometimes.

What was then left was to add support to the boot ROM to work out which SD card slot to use (as mentioned, support for using both at once will come later). Basically we try to reset the SD card in slot 0, and if that fails, then we try resetting the other one:

   ; Work out if we are using primary or secondard SD card

                ; First try resetting card 0
                lda #$c0
                sta $d680
                lda #$00
                sta $d680
                lda #$01
                sta $d680

                ldx #$0f
@morewaiting:
                jsr sdwaitawhile

                lda $d680
                and #$03
                bne trybus1

                phx

                ldx #<msg_usingcard0
                ldy #>msg_usingcard0
                jsr printmessage

                plx            

                jmp tryreadmbr
trybus1:
                dex
                bne @morewaiting

                lda #$c1
                sta $d680
                ldx #<msg_tryingcard1
                ldy #>msg_tryingcard1
                jsr printmessage

tryreadmbr:


Whichever we choose is then the SD card used by the system until next reboot.  The freeze menu and FDISK needed to be patched to handle the bit that indicates which SD card is being used, but other than that, it was pretty uneventful, and now when you boot, you get a message that indicates which SD card bus is being used, in this case, bus 0:


So now we can send Falk his board back, so that he can finish working on the GEOS port for the MEGA65, which we are all very much looking forward to.

Friday, 1 March 2019

Floppys, floppys everywhere!

A number of you will recall that we have been asking questions about floppy drives, and even asking people to hunt through their old floppy drive collections, so that we can get enough for trying out which will fit best etc.

First though, is the question of whether we will include a floppy drive in the MEGA65.  The survey confirmed our existing belief, that more people would like the MEGA65 to have a floppy drive than those against:



We had a total of 184 valid answers from mostly Europe, North America and Australia, with special mentions for Argentina and Iceland.  I was a bit surprised to not see any entries from New Zealand, but that's okay.  Basically we see a general matching of interest to where the Commodore 8-bit computers were well known.  What is most interesting is that on a per-capita basis, it is Denmark and then Australia and Germany that have the highest number of responses.  But enough of me in academic data analysis mode! 


So given that more people want the drive in than out, we had to figure out how and where we could find enough floppy drives for those who want them (we will still likely make the inclusion of the drives optional).

Of course floppy drives are no longer manufacturered, and although as recently as 2016 or 2017 we were able to find brand-new stock in Chinese warehouses, we have had no such luck this time around.  

We even called the German headquarters of ALPS who still make various switches and things, but no longer floppy drives, if they had a few palettes of them hidden away some where.  This was quite a nice call with them, and they were very sympathetic, but unfortunately knew of no stock anywhere.  They did reveal something interesting though: Apparently they are being asked about floppy drives more frequently of late.  Could it be that floppies will make a come back like vinyl records? Probably not.

Anyway, so we had to try to find a large quantity of floppies, but recognised that they would likely have to be used ones, rather than new ones.  But even if they were used, we wanted to find a single supplier with a single model of drive, so that we don't have to worry about eject buttons with different mechanisms or locations to interface to the case etc.

After some searching, we found what we were after: A local supplier here in Germany who has some quantity of different models, including a large number of ALPS 3.5" 1.44MB drives.  This was as good as we could hope for, as the ALPS drives are built like little tanks.  They kindly sent us some very fancy photos of an example drive for us to look at:


 They even took the top off one to show us the internals:

Note that this drive had the front panel removed, which we had requested, so that we could see the eject button mechanism etc, since in the MEGA65 only the slot will be visible.

So, we were satisfied we had a solution, and have thus bravely ordered our first shipment of floppy drives, which is also the first component we have purchased in bulk for the first production run of the MEGA65, which is a little milestone in itself.  After a tense couple of weeks of not receiving a tracking number for the shipment, they suddenly arrived yesterday.  Here are some shots of me starting to unpack several hundred floppy drives:





So now we need to make sure that everything will work together as expected, and have one of these drives connected to the R1 PCB prototypes of the MEGA65 here in Darmstadt:

Fixing Sprite Rendering Problem

After all the fiddling around with video modes a while back, a bug with sprite handling has crept in, where gaps would appear between sprites that were placed side-by-side, e.g., as in the big planet display on Gyrrus:



Or between the halves of the 16-colour sprites in Daniel's Beach Demo test program for the MEGA65:



At first I thought it was pixel edge timing funniness, but it turns out after a little inspection that the left column of pixels in a sprite are only one pixel wide instead of the correct two pixels wide (when at 320x200), as I was able to confirm by setting the first few pixels in the left and right column to check for clues.  So, the question is what is causing this problem?

To figure out the likely cause, I first checked to make sure that the problem happens whether or not sprites are horizontally expanded, and indeed, it does. Also, it is still exactly one physical pixel that is missing, i.e., the gap does not get wider if the sprites are horizontally expanded.

This suggests something about the logic that triggers when on a raster line a sprite should begin being drawn is to blame.  Quite possibly it triggers the logic to advance the pixels one cycle before it actually begins outputting sprite data.

There is some evidence in support of this, in that if the sprites are set to un-expanded H640 mode, i.e., where each sprite pixel is only one physical pixel wide, then the left pixels simply don't appear.


So I started looking at the logic for the sprite pixel advancing, and found that the sprite left edge could be triggered on a cycle when it is not a visible pixel edge.  As a result, an update happens to the sprite X pixel position on this partially wide pixel.  The fix turned out to be quite simple:

@@ -299,11 +300,19 @@ begin  -- behavioural
 --      else
 --        report "x_in = " & integer'image(x_in) & ", != sprite_x = " & integer'image(to_integer(sprite_x));
 --      end if;
+
+      -- Make sure we don't start a sprite edge except on an output pixel edge,
+      -- to stop the left pixel column being trimmed by one clock tick
+      if (x_in_sprite_soon= '1') and (pixel_strobe = '1')  then
+        x_in_sprite_soon <= '0';
+        x_in_sprite <= '1';
+      end if;
+
       if (x_in = to_integer(sprite_x))
         and (x_in /= x_last)
         and (sprite_enable='1')
         and ((y_top='1') or (sprite_drawing = '1')) then
-        x_in_sprite <= '1';
+        x_in_sprite_soon <= '1';         x_expand_toggle <= '0';
         report "SPRITE: drawing row " & integer'image(y_offset)
           & " of sprite " & integer'image(sprite_number)


Basically I have added an extra signal that notes when the sprite X starting position is reached, but then delays it until the next physical pixel edge.  I like it when things are simple to fix.  The result is that the problem is corrected, as the following screen-shots show:


Now if I only I can fix the remaining bitplane problems so quickly.  But that will have to wait for another post.

Thursday, 24 January 2019

The MEGA65 at Linux Conf AU

This week I am at Linux Conf AU, where I have, among other things, given a presentation about the MEGA65, using the MEGA65:


The cover slide was produced using a PNG to MEGA65 full-colour image converstion utility I wrote, and the main slides using MegaWAT, which I wrote with Lucas, a student, over the past few months in preparation for this, and in general, for being able to use the MEGA65 to introduce itself.  The source is at github.com/MEGA65/MegaWAT.