Monday 25 November 2019

The long winding path to getting HDMI Audio working

But my notes assure me it has been only 8 or 9 days that it has taken me to get HDMI audio working, but it feels like a month!

Having spent a few days to get the HDMI video finally working recently, I was keen to get HDMI audio working as well, so that we could just cross the whole HDMI thing off the list of major outstanding tasks for the MEGA65.  It should have been easy, but turned out to be quite nasty for a variety of reasons, not the least of which was a little tiny typo... but more on that later.

The ADV7511 HDMI driver chip we are using supports audio as well as video, and of course we want to have the MEGA65 with with that, so that it is super-easy for people to plug a MEGA65 into their TV or monitor, and get sound as well as picture.  Having got the MEGA65 and MEGAphone prototypes working, I am beginning to get familiar with digital audio formats. 

I was expecting to use the same I2S audio format that the MEGAphone uses for various of its audio paths.  However, the MEGA65 R2 PCB has only SPDIF audio hooked up. No problem. After a bit of hunting around, I found a nice SPDIF implementation in VHDL that I could use.  It didn't take too much hassle to get that plumbed in and working. 

It was then also a bit of additional fiddling with ADV7511 I2C register settings (and research to find out what I wasn't setting) to get some audio coming out in test bitstreams. This took a bit longer than expected, because at first I didn't realise that I was hitting a rather weird problem: Enabling HDMI audio with the PAL video mode we are using caused the HDMI output to completely fail, i.e., the screen would go to sleep, as though there was no video signal. 

Once I figured out that that was happening and switched to using the NTSC mode to work on, I soon had reasonable audio.  I say reasonable, because it was quite recognisable, but also quite distorted. There were a number of small bugs here, as well as simply reducing the audio output level to a level that agreed with the ADV7511.  I also increased the sample rate to 192KHz, since HDMI supports that, and I figured it couldn't hurt.

What then followed was several long frustrating nights, as I tried to figure out what was going on with this crazy PAL video mode problem.  Why on earth would turning audio on with a PAL signal cause the signal to fail?  Why would a monitor even care whether the signal was PAL or NTSC when processing the audio?  These and many other questions kept flying through my head.

To help track the problem down, I reworked the whole HDMI I2C setup code, so that I could actually direct memory map the I2C registers, so that I could see what the ADV7511 was thinking about things, as well as trying to tweak any registers that seemed like they might be the culprit. It turned out that none of them were the cause, although I recall that I did improve a few of the settings along the way. It also meant that I wrote a nice little HDMI debug utility that shows the status of many of these registers, and reports on the detected video mode etc:



The PAL problem was at the time still causing me increasing frustration, as there was no apparent cause for it, as can be seen in the rather long github issue log as I tried various things.  So I resorted to asking for help on the Analog Devices forum, and then progressively mutating the NTSC video mode until it matched the PAL video mode, to try to find the actual cause. It was this last idea that finally let me solve the problem:  I had a typo in the VSYNC setup for the PAL video mode, that caused the VIC-IV to produce pixel data during the first line of VSYNC.

Once it started working, it was obviously a very great relief.  Commando sounds excellent.  I think there might be some minor problems with stereo and level normalisation causing some clipping due to DC bias on the digital samples. But those are all feel like achievable relatively small tasks, now that we have the fundamental audio working.

Friday 22 November 2019

Writing the 2019 Christmas Demo

Today we have another guest post, this time from Anton, describing how he created the nice little Christmas Demo for the C64, C65 and MEGA65.  This is a nice little program to explore, because it works out which machine you are on, and varies the display accordingly.  But let's have Anton explain it in his own words...
Hi everybody, i wanted to present you with a small background info about the
MEGA65 BASIC 2 christmas demo I have just coded together with Paul.
A Forum64 member (ZeHa), started last year a project on forum64.
The idea was, to bring back the times of the 80’s, when you went to your local store, bought the latest computer magazine and started, once at home, to type the listings into your beloved 8-bit machine. So he collected last years, xmas themed BASIC listings from board members and put them together in a magazine.

So, this year, he contacted us, the MEGA65 team, if we wouldn’t be interested in providing a nice program as well. We’ve discussed this in the team and we all loved the idea. So I agreed to program something in BASIC. (I haven’t done any BASIC coding since the 80’s…..)

I knew from the beginning, that I would like to code something, that would run on every C64 but I also wanted to demonstrate, what the MEGA65 is capable of.
So that’s when I settled on BASIC 2. One of the biggest advantages of the MEGA65 really is, that you can be in normal C64 mode, you activate the VIC-IV features by Poking :

POKE 53295,71:POKE 53295,83


and you have all the VIC-IV features available at your hand. Easy as that !!!

I started to think about the demo and xmas-themed requirements and slowly an idea formed into my head. I contacted Paul and asked him, if there is a way to find out, if  there is a VIC-II present, like on the c64 or a VIC-III like on the c65 or a VIC-IV, the MEGA65 is using. So after some testing we had a nice code snippet ready to check, what machine our program is running on:
(I love the name, we call it “Knock Knock”-routine)

13710 REM *** "knock knock" TO CHECK WHAT VIC IS USED (c64/c65/MEGA65) ***
13720 REM In c65 Mode we cannot safely write to 53295, so we test a different way
13810 IF PEEK(V+24)AND32THENGOTO14410
13910 POKEV,1:POKEV+47,71:POKEV+47,83
14010 POKEV+256,0:IFPEEK(V)=1THEN VC=65:C$="VIC-IV":RETURN
14110 POKEV,1:POKEV+47,165:POKEV+47,150
14210 POKEV+256,0:IFPEEK(V)=1THEN VC=65:C$="VIC-III":RETURN
14310 VC=64:C$="VIC-II":RETURN
14320 REM we assume we have a c65 here
14410 V1=PEEK(V+80):V2=PEEK(V+80):V3=PEEK(V+80)
14510 IF V1<>V2 OR V1<>V3ORV2<>V3THEN VC=65:C$="VIC-IV":RETURN
14610 GOTO14110
So after I was able now to check, what machine my code is getting executed on, I could start with my demo. I wanted to make something simple, nice to watch and completely in BASIC.
Several people have asked already, how the 15 colour sprites on the MEGA65 are working, so I thought, this should go into the demo as well.

The idea shaped. After I found out, with a lot of help from Paul (Thanks Paul !), how the 15 colour sprite works, I started to design a 15 color sprite.

For a rough understanding:
The c64 sprites are using in HiRes mode 24bit x 21 bits so a standard sprite is 24 by 21 pixels
The multicolor sprites are using 2  bits for each color which leaves us with 12 doublewide pixels x 21 pixels. So a sprite on the c64 is using 63B (64)Bytes (one Byte stays empty).
The  MEGA65 VIC-IV is able to show a 15 color sprite, which is 16 pixels horizontally x 21 pixels vertically.
Each pixels colour is set by one Nibble (4bits) so a MEGA65 15colour sprite is 64bits horizontally and 21 bits vertically. This means:
4bits x 16 =  64 bits horizontally (8 Bytes)
64 x 21 = 1344 bits or 168 Bytes.
This means, that for a 15 color VIC-IV sprite you have 168B of Data.
The memory area at $0340 would be perfect. So I started drawing a concept.
Have a look: (PS, the blank middle line was removed by moving the right side of the tree one pixel to the left)
I have to say I was amazed, to see how much you can realize with a sprite with such dimensions !
Paul wrote a nice code snippet, which might not be the fastest routine to get the 15 colour sprite poked to the right memory address area, but it was a very good study example of HOW it works.
Have a look here:
(all the standard sprite commands like, positioning, sprite pointer, etc. remain exactly like it would be a normal HiRes sprite. here in this part you only see the commands, that are different from VIC-II)
(You can see, that I am using in this routine already the checks done in the previous code snippet, to see, what VIC is used.)

45 REM IF MEGA65 ENABLE VIC-IV FEATURES
48
IFC$="VIC-IV"THEN POKE V+47,71:POKE V+47,83

255 REM *** VIC-IV 15 COLOR SPRITE SETUP ***
260
REM IF NO MEGA65 JUMP TO 390
265
IF C$="VIC-II" OR C$="VIC-III" then goto 390
270
REM SET ADDRESS 15COL SPRITE TO $0340 (832)
275
AD=768+64
280
REM MAKE SPRITE 3 - 8 AS 15COLOR SPRITES AND MAKE THEM USE 64 BIT
285
POKE V+107,252:POKE V+87,252
290
REM COPY STANDARD COLORS OVER FOR MULTICOL SPRITES 3 - 8
295
FORI=16TO255:FORJ=1TO3:POKEV+256*J+I,PEEK(V+256*J+(I AND 15)):NEXTJ,I
315
REM READ 15COL SPRITE DATA
320
READN$:IFN$="end"THEN 390
325
REM JUMP TO DECODE ROUTINE
330
GOSUB 345
335
GOTO 320
340
REM DECODE STRING OF NYBLS IN N$ AT ADDRESS AD (832)
345
L=LEN(N$)
350
FOR I=1 TO (L/2+1):POKE AD+I,0
355
FOR I= 1 TO L:N=ASC(MID$(N$,I,1))-64:IFN<0THEN N=0
360
B=AD+INT((I-1)/2):IF (I AND 1)=1 THEN N=N*16
365
VA=PEEK(B):POKE B,VA OR N:PRINT"{home}";VA:NEXTI
370
AD=AD+INT(I/2)375 IF (L AND 1) THEN AD=AD+1
380 RETURN

1445 REM 15 COLOR TREESPRITE DATA 
1450 REM "-" = TRANSPARENT, "A"-"O"" = COLOURS 1 TO 15 
1455 DATA "------HGH-------"
1460 DATA "------GGG-------"
1465 DATA "------HGH-------"
1470 DATA "-------G--------"
1475 DATA "------EEH-------"
1480 DATA "-----E-EBE------"
1485 DATA "------ENB-------"
1490 DATA "-----EEEEM------"
1495 DATA "----EHEEEEE-----"
1500 DATA "---E-B-EE--E----"
1505 DATA "----EBEEENE-H---"
1510 DATA "---CEEEHEEEEB---"
1515 DATA "--EE--EBE--EB---"
1520 DATA "---HEEEBCEE-----"
1525 DATA "---BEEEEEEEE----"
1530 DATA "--EBE-EEEEEHE---"
1535 DATA "-EE--EEMEE-BEE--"
1540 DATA "H--EEEEECEEB----"
1545 DATA "BEEENEEEEEEEEE--"
1550 DATA "BEEEE--I--EECEE-"
1555 DATA "-------I--------"
1560 DATA "END"


I would like to mention, by setting the sprite color, you define the transparent color.
So if our Tree is sprite 3, by setting 53290 ($D02A) to 0 (Poke53290,0) you set Black(0) as transparent color for sprite 3 (53290).
Line 290 & 295 might also be worth mentioning as well. There we copy the RGB values of the 16 standard colors from Sprite 1 color bank over to the Sprite colour bank of sprite 3 – 8.
This means, you can set not only 15 colours per sprite, but also can define how these colors look like.
You have the RGB values under your control.



  
OK, but back to the demo. So I was drawing several other sprites (since I already knew, that people who have  a normal c64 or a c65 wouldn’t be able to see the 15color sprite), and started to put everything together as I continued to program in BASIC 2 I realized soon, that on a normal c64 with 1 MHz I would not be able to realise all the things I wanted to show.
But the MEGA65 is able to switch between 1MHz/2MHz/3.5MHz and 40MHz !!!




This was the idea I was looking for !!!  enable certain features of the demo, only if the machine is able to support a certain speed:
C64 max 1MHz.
C128 max 1MHz (2MHz not useable, since FAST mode on c128 disables screen)
C65 1MHz/3.5 MHz
MEGA65 max 40 MHz
 

So after I knew, what VIC my program is running on, I was able to tell what the maximum speed would be, that this machine can support.
So I needed some code to do the frequency change. After checking the VIC-III and VIC-IV registers, since the official MEGA65 manual is having all the necessary information:


I came up with this code snippet:


935 REM *** FREQUENCY CHANGE ***
940 REM SWITCH TO 2MHZ
945 IF MH=1 AND C$="VIC-IV" THEN GOSUB985:POKEV+48,1:MH=2:GOTO995
950 REM SWITCH TO 3.5 MHZ
952 IF MH=1 AND C$="VIC-III" THEN POKEV+49,64:MH=3.5:RETURN
955 IF MH=2 THEN GOSUB985 POKE0,64:MH=3.5:GOTO995
960 REM SWITCH TO 40MHZ
965 IF MH=3.5 AND C$="VIC-IV"THEN GOSUB985:POKE0,65:MH=40:GOTO995
970 REM SWITCH TO 1 MHZ
972 IF MH=3.5 AND C$="VIC-III" THEN POKEV+49,0:MH=1:RETURN
975 IF MH=40 THEN GOSUB985:POKE0,64:MH=1:GOTO995 
980 REM DISABLE VIC-IV FEATURES
985 POKEV+47,0:POKEV+48,0:RETURN 990 REM ENABLE VIC-IV FEATURES
995 POKEV+47,71:POKEV+47,83
1000 IF MH=40 THEN POKEV+49,0
1005 IF MH=3.5 THEN POKEV+49,64
1010 RETURN

So the c64 would run our nice Christmas demo with the least functions, while on the MEGA65
You can see all the functions implemented (including the 15 colour demo Sprite).
So if the demo is running on a machine > c64/c128 an extra text is shown, which asks you to press
(depending again on what machine it’s running) “SPACE” to cycle between standard Multicolour Sprite and 15 colour VIC-IV Sprite, or “F” to cycle through the freqencies.

This is more or less, the main idea behind the demo. It will run on a c64 also on a c65 and on the MEGA65 and it shows some of the features the MEGA65 offers.
So if you are interested in the demo, hop over to forum64 (this is also the official MEGA65 forum)
Just mention in the Thread, that you want to receive a copy of the forum64 2019 christmas magazine.

So to conclude: I want to wish all of you a merry Christmas 80’s style...

Anton