@pik33 said:
... People from RPi forums overclocked some cards up to 85 MHz, ...
I just did a quick search of RPi SD controller and it looks like that thing has a proper hardware controller for the job. Which means they'll be using the SD data protocol rather than SPI. Which probably means they tell the card to go faster.
My recent examinations with the oscilloscope have shown that SPI mode is weakly driven. The slewing has a notable R-C curve. Even at 25 MHz the data is notably lagging the clock and, maybe more importantly, is already attenuated. This is definitely impacting reliability at higher frequencies.
By itself, this weak drive of the SD cards is enough to explain why different boards/kits/cards we have produce different outcomes above 25 MHz.
EDIT: Interesting, quickly reading the SD specs, CMD6 looks be the one for requesting faster operation. And most impressively is it's listed as supported in SPI mode ... and it's not used in our current implementation ...
I read about CMD6 and this can be the key. From the specification manual:
Physical Layer Simplified Specification Version 6.00
67
Application Notes:
Default setting is 0.72W. In this mode, UHS-I and UHS-II card may not provide the maximum
performance. The Speed Grade performance is defined at 1.44W mode. The maximum
performance of the card is available when setting of this field covers the maximum current (power)
of the card that can be read by CMD6 mode 0
I managed to extract a "bare" 6502 emulator from macca's COMPUKIT UK101. Attached test program blinks a led at P56 using overengineered way. The test loop puts 0 and 1 to the 6502 RAM at $500, the 6502 rewrites the value to $501, the loop gets a byte from $501 and set the LED according to it.
6502 works in 3 instruction loop:
*=$600
lda $500
sta $501
jmp $600
As the 6502 emulator now works, I can write a real .sid files player instead of .dmp. While moving the emulator out of COMPUKIT i learned its structure, so I think I can add these "illegal" instruction to it, too
The Basic compiler doesn't accept "debug" in asm shared section! I wrote a topic in Basic subforum. Debugging asm stuff has to be done in Spin only
@pik33 said:
As the 6502 emulator now works, I can write a real .sid files player instead of .dmp. While moving the emulator out of COMPUKIT i learned its structure, so I think I can add these "illegal" instruction to it, too
I added some of the instructions already, not much tested but hopefully the needed are working.
The instructions are prefixed with a * in the lut table.
It seems it depends on the card. One of card I use is not stable enough at 7, so I set 8 for it, the second one works at 7 without problems. Even at 8 the driver is fast enough for all I need for the player.
Now I play with several ideas at once. First I want to attach a 6502 emulator to play real .sid files. Second I have an idea how to do a realtime windows manager using 4bit PSRAM.
After all adventures with Basic's "get #" the real .sid files now play. To do now is: to clean the mess, , to add illegal opcodes - Linus Akesson's songs don't play without these, and to add the selection of subtunes to the user interface. Then debug all of this including the SID emulation after all these changes.
The current state of the project is now pushed to Github.
@pik33 said:
As the 6502 emulator now works, I can write a real .sid files player instead of .dmp. While moving the emulator out of COMPUKIT i learned its structure, so I think I can add these "illegal" instruction to it, too
I added some of the instructions already, not much tested but hopefully the needed are working.
The instructions are prefixed with a * in the lut table.
Added this. While "A mind is born" now plays, "Lunatico" still doesn't play - I have my own 6502 for RPi/Ultibo so I will now try to find what he used in his songs and complete the list. I also replaced halts with nops to make debugging easier.
procedure lax;
begin
value := getvalue;
a:=(value and $00FF);
x:=a;
if (a and $0080)<>0 then setsign else clearsign;
if (a and $00FF)<>0 then clearzero else setzero;
end;
procedure sax;
begin
putvalue(a and x);
if (a and x and $0080)<>0 then setsign else clearsign;
if (a and x and $00FF)<>0 then clearzero else setzero;
end;
procedure dcp;
begin
value:=getvalue;
value:=(value-1) and 255;
putvalue(value);
cmp;
end;
procedure isb;
begin
value:=(getvalue+1) and 255;
putvalue(value);
value := value xor $00FF;
aresult := word(a) + value + (status and FLAG_CARRY);
if (aresult and $FF00) <>0 then setcarry else clearcarry;
if (aresult and $00FF)<>0 then clearzero else setzero;
if ((aresult xor a) and (aresult xor value) and $0080)<>0 then setoverflow else clearoverflow;
if (aresult and $0080)<>0 then setsign else clearsign;
if (status and FLAG_DECIMAL)<>0 then
begin
inc(clockticks6502);
clearcarry;
if ((a and $0F) > $09) then a += $06;
if ((a and $F0) > $90) then
begin
a += $60;
setcarry;
end;
end;
a:=byte(aresult and $00FF);
end;
procedure slo;
begin
value := getvalue;
aresult := value shl 1;
if (aresult and $FF00) <>0 then setcarry else clearcarry;
if (aresult and $00FF)<>0 then clearzero else setzero;
if (aresult and $0080)<>0 then setsign else clearsign;
putvalue(aresult);
value := aresult;
aresult := a or value;
if (aresult and $0080)<>0 then setsign else clearsign;
if (aresult and $00FF)<>0 then clearzero else setzero;
a:=byte(aresult and $00FF);
end;
procedure rla;
begin
value := getvalue;;
aresult := (value shl 1) or (status and FLAG_CARRY);
if (aresult and $FF00) <>0 then setcarry else clearcarry;
if (aresult and $00FF)<>0 then clearzero else setzero;
if (aresult and $0080)<>0 then setsign else clearsign;
putvalue(aresult);
aresult := a and aresult;
if (aresult and $00FF)<>0 then clearzero else setzero;
if (aresult and $0080)<>0 then setsign else clearsign;
a:=byte(aresult and $00FF);
if (penaltyop<>0) and (penaltyaddr<>0) then dec (clockticks6502);
end;
procedure sre;
begin
value := getvalue and $FF;
aresult := value shr 1;
if (value and 1)=1 then setcarry else clearcarry;
if (aresult and $0080)<>0 then setsign else clearsign;
if (aresult and $00FF)<>0 then clearzero else setzero;
putvalue(aresult);
aresult := a xor aresult;
if (aresult and $0080)<>0 then setsign else clearsign;
if (aresult and $00FF)<>0 then clearzero else setzero;
a:=byte(aresult and $00FF);
end;
procedure rra;
begin
value := getvalue;;
aresult := (value shr 1) or ((status and FLAG_CARRY) shl 7);
if (value and 1)=1 then setcarry else clearcarry;
if (aresult and $00FF)<>0 then clearzero else setzero;
if (aresult and $0080)<>0 then setsign else clearsign;
putvalue(aresult);
value := aresult;
aresult := word(value)+a+(status and FLAG_CARRY);
if (aresult and $FF00) <>0 then setcarry else clearcarry;
if (aresult and $00FF)<>0 then clearzero else setzero;
if ((aresult xor a) and (aresult xor value) and $0080)<>0 then
setoverflow
else
clearoverflow;
if (aresult and $0080)<>0 then setsign else clearsign;
if (status and FLAG_DECIMAL)<>0 then
begin
inc(clockticks6502);
clearcarry;
if ((a and $0F) > $09) then a += $06;
if ((a and $F0) > $90) then
begin
a += $60;
setcarry;
end;
end;
a:=byte(aresult and $00FF);
end;
procedure anc;
begin
ana;
if (a and $80)>0 then setcarry else clearcarry;
end;
procedure alr;
begin;
value := getvalue;
aresult := (a and value) shr 1;
if (aresult and $0080)<>0 then setsign else clearsign;
if (aresult and $00FF)<>0 then clearzero else setzero;
a:=aresult;
end;
procedure arr;
begin;
value := getvalue;
aresult := a and value;
aresult := (aresult shr 1) or ((status and FLAG_CARRY) shl 7);
if (aresult and 96)=96 then begin setcarry; clearoverflow; end
else if (aresult and 96)=0 then begin clearcarry; clearoverflow; end
else if (aresult and 96)=32 then begin clearcarry; setoverflow; end
else begin setcarry; setoverflow; end;
a:=aresult;
end;
procedure xaa;
begin;
a:=x;
value:=getvalue;
aresult := a and value;
if (aresult and $00FF)<>0 then clearzero else setzero;
if (aresult and $0080)<>0 then setsign else clearsign;
a:=byte(aresult and $00FF);
end;
procedure ahx;
begin;
aresult:=a and x and 7;
putvalue(aresult);
end;
procedure tas;
begin;
sp:=a and x and (ea shr 8) +1;
putvalue(sp);
end;
procedure shy;
begin;
value:=(((ea) shr 8) and y) +1;
putvalue(value);
end;
procedure shx;
begin;
value:=(((ea) shr 8) and x) +1;
putvalue(value);
end;
procedure las;
begin;
value:=getvalue and sp;
sp:=value;
x:=value;
a:=value;
end;
procedure axs;
begin;
value := getvalue;;
x := word(a and x) - value;
if (x >= (value and $00FF)) then setcarry else clearcarry;
if (x = (byte(value and $00FF))) then setzero else clearzero;
if (x and $0080)<>0 then setsign else clearsign;
end;
procedure atx;
begin;
value := getvalue;;
a:=(a and value and $00FF);
x:=a;
if (a and $0080)<>0 then setsign else clearsign;
if (a and $00FF)<>0 then clearzero else setzero;
end;
So I found a good disassembler online and tried to disassembly non-working Akesson's Lunatico side 1. The disassembler can determine the format and works with .sid files which makes thinhs easier.
Implemented. All previous illegal instructions still fit in the cog so I moved them there, but axs had to go to LUT. Lunatico now plays.
... but something in the player has to be debugged, there are errors with a lot of SIDs I am trying to play. Either I destroyed something making all this sid emulation revolution (I will try to link the original SIDCog to the player and compare) or somewhere else in the player. These errors are not repeatable. One of the channels can stop playing, sometimes the wrong waveform is selected (eg. triangle instead of noise)
The player after all of this is messy again and needs cleaning, which can also help with finding bugs.
The real .sid files now play. Not all and not all without errors, but most of them play.
After most of the memory hungry things was moved to the PSRAM I cleaned the HUB memory map.
"Overoptimizing" the SID main loop caused the SID waveform #0 (which is not a waveform at all and should not be played) to be played as a combined waveform #3. I have no place (or rather time) in the SID cog itself to restore the check and react, so I did this in the player itself, which simply mutes the channel if the waveform# is 0.
This error affected "Lunatico Side 2" (and of course many more, but this was the tune which madke me to find it)
There is still an error which caused "That's The Way It Is" to play - in several places - triangle (or saw?) instead of noise. However, there is no such error if I play the tune from .dmp instead of .sid so it is related with a 6502 or the interface between 6502 and the SID emulation. Maybe I should save 6502 registers after calling play and restore them before the next call..
The .wav playing procedure clears the buffer at the end. I didn't change the address when I changed the memory map. The result: total crash at the end of .wav file. Corrected.
Dancing sprites effect.
I did this effect several years ago for the RPi based player. The SID frequency controls sprite x position, while the sustain level controls the Y position
Now, as the video driver can display (up to 16) sprites I managed to implement this also on a P2.
While playing Amiga modules, sprites are controlled by the channel volume and period.
This is the result:
The current version of player is controllable by a mouse. I use my RPi interface but of course any mouse driver can be used so I have to try and fit the P2 USB kbd and mouse drivers.
The HDMI driver has also updated to mask the part of the sprite which goes over the right screen border.
DVI only does video. That's where HDMI goes its own way.
HDMI-Audio is packet based, during blanking, using the video channels. Sample rate is a whole fraction of the HDMI link speed. Resampling is required if passing through from another digital source.
... and, if someone is interested in (and, sure, is venturous enough), perhaps there is
at least one place to start (though I don't even know where it can lead to (or if it can even "land") somewhere...
A few years ago now I got some HDMI sound working with an earlier HDMI video driver I'd worked on before I moved to a more universal driver to include VGA etc but it still was a bit flaky. I heard my test tones on a cheap LCD monitor with HDMI but not a proper plasma TV so there was still something not 100% correct with the audio data or headers (probably just one field wrong somewhere). I put the effort on hold, and there are potentially some IP licensing issues to deal with if you want to do it officially. It is certainly doable on the P2 but is quite complex. I learned what I could via the various FPGA implementations people have posted online.
@rogloh It was your code I was thinking of. I was curious if anyone picked up the ball and ran with it. I am sure IP issues exist no matter if sound is added or not, if an HDMI connector is used. I don't know the details of all that, and really just want to remain willfully ignorant of it.
This is the first version of the player compiled for P2-EC32.
To use:
attach a HDMI accessory to pin #0 and AV accessory to pin #8
copy some music: 44 kHz wav, sid, dmp, mod, spc into the SD card and place it into the EC32
upload or flash the binary
The control:
method 1 (simplest): you have no RPi Zero. use the keyboard connected to a PC and the Flexprop's serial terminal set to 2 Mbps baud rate. No mouse in this mode
method 2: (for RPi owners): you have a RPi Zero and a USB hub/RPi keyboard in your drawer. Unpack the v0.01 to FAT32 formatted empty SD. Place SD into RPi Zero. Attach a mouse and a keyboard to a Pi. Connect Pi Tx (pin 8) to P2 pin 16. Connect grounds. Power up a Pi. Now a mouse and a keyboard attached to a Pi should work. There are bugs in RPi code, if it stop responding, it needs resetting. To be debugged and converted to a RPi Zero 2.
method 3: (most complex): you have your own working keyboard and mouse driver, unpack the source (P2P16.zip) and hack retrocog.spin2.
The retrocog.spin2 is a mess in the transition process. There will be a readkey() function instead of passing it via the hub.
@pik33 said:
After all adventures with Basic's "get #" the real .sid files now play. To do now is: to clean the mess, , to add illegal opcodes - Linus Akesson's songs don't play without these, and to add the selection of subtunes to the user interface. Then debug all of this including the SID emulation after all these changes.
The current state of the project is now pushed to Github.
Comments
I just did a quick search of RPi SD controller and it looks like that thing has a proper hardware controller for the job. Which means they'll be using the SD data protocol rather than SPI. Which probably means they tell the card to go faster.
My recent examinations with the oscilloscope have shown that SPI mode is weakly driven. The slewing has a notable R-C curve. Even at 25 MHz the data is notably lagging the clock and, maybe more importantly, is already attenuated. This is definitely impacting reliability at higher frequencies.
By itself, this weak drive of the SD cards is enough to explain why different boards/kits/cards we have produce different outcomes above 25 MHz.
EDIT: Interesting, quickly reading the SD specs, CMD6 looks be the one for requesting faster operation. And most impressively is it's listed as supported in SPI mode ... and it's not used in our current implementation ...
I read about CMD6 and this can be the key. From the specification manual:
I managed to extract a "bare" 6502 emulator from macca's COMPUKIT UK101. Attached test program blinks a led at P56 using overengineered way. The test loop puts 0 and 1 to the 6502 RAM at $500, the 6502 rewrites the value to $501, the loop gets a byte from $501 and set the LED according to it.
6502 works in 3 instruction loop:
As the 6502 emulator now works, I can write a real .sid files player instead of .dmp. While moving the emulator out of COMPUKIT i learned its structure, so I think I can add these "illegal" instruction to it, too
The Basic compiler doesn't accept "debug" in asm shared section! I wrote a topic in Basic subforum. Debugging asm stuff has to be done in Spin only
I added some of the instructions already, not much tested but hopefully the needed are working.
The instructions are prefixed with a * in the lut table.
Pik,
I couldn't keep sysclock/7 it wasn't reliable enough.
It seems it depends on the card. One of card I use is not stable enough at 7, so I set 8 for it, the second one works at 7 without problems. Even at 8 the driver is fast enough for all I need for the player.
Now I play with several ideas at once. First I want to attach a 6502 emulator to play real .sid files. Second I have an idea how to do a realtime windows manager using 4bit PSRAM.
After all adventures with Basic's "get #" the real .sid files now play. To do now is: to clean the mess, , to add illegal opcodes - Linus Akesson's songs don't play without these, and to add the selection of subtunes to the user interface. Then debug all of this including the SID emulation after all these changes.
The current state of the project is now pushed to Github.
Added this. While "A mind is born" now plays, "Lunatico" still doesn't play - I have my own 6502 for RPi/Ultibo so I will now try to find what he used in his songs and complete the list. I also replaced halts with nops to make debugging easier.
So I found a good disassembler online and tried to disassembly non-working Akesson's Lunatico side 1. The disassembler can determine the format and works with .sid files which makes thinhs easier.
Here it is: https://www.white-flame.com/wfdis/
The start of the file looks like this and what he used and is not yet implemented is instruction $CB, axs, or sbx.
The code should be this:
Implemented. All previous illegal instructions still fit in the cog so I moved them there, but axs had to go to LUT. Lunatico now plays.
... but something in the player has to be debugged, there are errors with a lot of SIDs I am trying to play. Either I destroyed something making all this sid emulation revolution (I will try to link the original SIDCog to the player and compare) or somewhere else in the player. These errors are not repeatable. One of the channels can stop playing, sometimes the wrong waveform is selected (eg. triangle instead of noise)
The player after all of this is messy again and needs cleaning, which can also help with finding bugs.
Sid subsong selection added by keys z,x while playing.
0.27.
The real .sid files now play. Not all and not all without errors, but most of them play.
After most of the memory hungry things was moved to the PSRAM I cleaned the HUB memory map.
"Overoptimizing" the SID main loop caused the SID waveform #0 (which is not a waveform at all and should not be played) to be played as a combined waveform #3. I have no place (or rather time) in the SID cog itself to restore the check and react, so I did this in the player itself, which simply mutes the channel if the waveform# is 0.
This error affected "Lunatico Side 2" (and of course many more, but this was the tune which madke me to find it)
There is still an error which caused "That's The Way It Is" to play - in several places - triangle (or saw?) instead of noise. However, there is no such error if I play the tune from .dmp instead of .sid so it is related with a 6502 or the interface between 6502 and the SID emulation. Maybe I should save 6502 registers after calling play and restore them before the next call..
The .wav playing procedure clears the buffer at the end. I didn't change the address when I changed the memory map. The result: total crash at the end of .wav file. Corrected.
Dancing sprites effect.
I did this effect several years ago for the RPi based player. The SID frequency controls sprite x position, while the sustain level controls the Y position
Now, as the video driver can display (up to 16) sprites I managed to implement this also on a P2.
While playing Amiga modules, sprites are controlled by the channel volume and period.
This is the result:
The current version of player is controllable by a mouse. I use my RPi interface but of course any mouse driver can be used so I have to try and fit the P2 USB kbd and mouse drivers.
The HDMI driver has also updated to mask the part of the sprite which goes over the right screen border.
Did anyone get sound working with HDMI (DVI)?
If yes, I don't know anything about this.
DVI only does video. That's where HDMI goes its own way.
HDMI-Audio is packet based, during blanking, using the video channels. Sample rate is a whole fraction of the HDMI link speed. Resampling is required if passing through from another digital source.
... and, if someone is interested in (and, sure, is venturous enough), perhaps there is
at least one place to start (though I don't even know where it can lead to (or if it can even "land") somewhere...
Fingers crossed here.
https://github.com/hdl-util/hdmi
A few years ago now I got some HDMI sound working with an earlier HDMI video driver I'd worked on before I moved to a more universal driver to include VGA etc but it still was a bit flaky. I heard my test tones on a cheap LCD monitor with HDMI but not a proper plasma TV so there was still something not 100% correct with the audio data or headers (probably just one field wrong somewhere). I put the effort on hold, and there are potentially some IP licensing issues to deal with if you want to do it officially. It is certainly doable on the P2 but is quite complex. I learned what I could via the various FPGA implementations people have posted online.
This System Verilog code may be helpful.
@rogloh It was your code I was thinking of. I was curious if anyone picked up the ball and ran with it. I am sure IP issues exist no matter if sound is added or not, if an HDMI connector is used. I don't know the details of all that, and really just want to remain willfully ignorant of it.
Repository moved to gitlab.
https://gitlab.com/pik33/P2-retromachine
This is the first version of the player compiled for P2-EC32.
To use:
The control:
The retrocog.spin2 is a mess in the transition process. There will be a readkey() function instead of passing it via the hub.
Edit: bad binary deleted.
OOPS! Something is wrong with .sid, .dmp and .wav files.. .spc and .mod works with EC... to be debugged....
... found. I compiled it without LFN.
Very nice!
This is how the player looks with a new Full HD vga driver
0.30
The first USB version, may be buggy. The binary needs EC32MB, HDMI at P0, AV board at P8 and USB board at P16
To do: keyboard autorepeat.