NEC PC-6001A Cassette WAV file issues...

Post Reply
alank2
Member
Posts: 116
Joined: Wed Mar 01, 2017 7:24 pm

NEC PC-6001A Cassette WAV file issues...

Post by alank2 »

I finally got my hands on a PC-6001A and after some repairs I have been trying to load some Z88DK generated code on it. Most emulators work with the cassette format which is a byte stream, but lacks some components of what would be in a WAV file for example. I've studied the nec.c and it seems to suggest that repeated zeros are part of the process, and has some code during WAV file generation that tests for this condition although I'm not sure why the code is doing what it is doing. Studying some of the cp6 files shows that there are places where they are streams of zeros and I have to presume that the CLOAD command loads these properly and continues. My theory is that it takes both zeros AND a steam of raw 1 bits to tell it to stop loading. You don't see these raw 1 bits in the CAS file because they are not a proper frame which begins with a 0, then 8 bits, then 1 and 1 for 2 stop bits.

The problem is that there can be a sequence of three zero's in the prefix_p6 - when this occurs, it will INSERT another "break" of all 1's. Because it is three zeros that triggers this, it ends the load. There was a warning under default: that said problems but it is disabled.

What is the point of doing this? I would think it would be better to just send everything and avoid doing an all 1's break until the end?
stefano
Well known member
Posts: 2137
Joined: Mon Jul 16, 2007 7:39 pm

Post by stefano »

Hello alank2, congratulations for your "new" PC-6001A !
The problem of different results between the emulated platform and the real hardware is quite common.
Feedback on this kind of topics is scarse and precious and I'm so glad you posted this message :)
I tested the wav format on PC6001 emulators only and it seems to me that making MESS react to the audio stream required some tuning. In any case this is my first thought on the possible causes..

First of all, it could be good to try an external wav converter, to exclude problems on the packaging phase (BASIC loader creation, etc..).

Then, I compared the appmake generated wav file to the audio file of the S-OS implementation for the PC6001, it sounded slightly different. appmake uses a bitrate of 44100, sometimes it is difficult to "tune" the periods exactly as it was on the original HW. I normally choose the higher pitch, so try lowering it a little:

if ( fast ) {
period1 = 8;
period0 = 14;
} else {
period1 = 9;
period0 = 21;
}

..please try changing "period0 = 21;" to 22 (or 23). It just "sounds" better, but sometimes an ear tuning suffices, let's remember that the tape speed couldn't be perfect in any case ;)


The NEC wav loader is, as you could probably see, a generic skeleton adjusted for the specific targets (pc88, pc6001..).
Im my comments I wrote:
It is a sort of a fast mode KansasCity format, very close to the SC-3000 one
four fast cycles for '1', two slow cycles for '0' but the samples I've seen seem to have also an amplitude variation, so here it is !

This means that the signal intensity used for the '1' bit sequence is lower than the "audio volume" used for '0' (about 1/3rd). I just found it like this and blindly replicated the same condition. Perhaps the volume needs to be carefully set, or it could also be that I totally misunderstood something :)

You might try to force everything at the same level:

if (bit) {
/* '1' */
for (i=0; i < period1; i++)
fputc (0x30,fpout);
for (i=0; i < period1; i++)
fputc (0xd0,fpout);
for (i=0; i < period1; i++)
fputc (0x30,fpout);
for (i=0; i < period1; i++)
fputc (0xd0,fpout);

..and try changing all the 0x30 values to 0x10, ...then 0xd0, to 0xf0.


The leading tone. In the old days one of the positive effects of the leading tone was to trigger the automatic recording volume (present in many tape recorders) and stabilize it before sending the real data. On the software side it avoided false positives, making the loader beginning its work only when the tape was correctly positioned. Long leading tones were used, in my opinion to avoid the users keeping the saved blocks too close, thus facilitating the tape positioning and avoiding the data being put too close to the beginning of the cassette. The NEC computers had a sequence of '1' bits, perhaps stabilizing the levels also for the hardware.


Please let me know if I can help further. I didn't fully understand your theory but it you give me a little more information we can hack the code in that direction.


Stefano
alank2
Member
Posts: 116
Joined: Wed Mar 01, 2017 7:24 pm

Post by alank2 »

stefano wrote:Hello alank2, congratulations for your "new" PC-6001A !
Thank you; I admit I'm pretty excited about actually having fixed something and have it working!
stefano wrote:The problem of different results between the emulated platform and the real hardware is quite common.
Feedback on this kind of topics is scarse and precious and I'm so glad you posted this message :)
I tested the wav format on PC6001 emulators only and it seems to me that making MESS react to the audio stream required
some tuning. In any case this is my first thought on the possible causes..
We can test it on real hardware now!! :)

What I was getting at above is that the .cas or .p6 cassette format file has the data elements in it, but it lacks the framing elements required for storing on tape/wav.

If I have any of this wrong, let me know!

It uses a UART style of communication with 1 start bit, 8 data bits (LSB), and two stop bits. I saw an extra one or two more "stop bits" when looking at the actual signal coming out of the PC-6001A, but these could just be extra mark/idle bits and are not required.

Typically UART just has mark (1) and space (0), but it is using binary frequency shift keying (BFSK) so there are really three states: off (no carrier, no sound), mark (2400 Hz), or space (1200 Hz). The amplitude is NOT different - mark and space are both of the same amplitude in the signal I saw coming from the PC-6001A.

One thing I was trying to determine is how it decides when an end of transmission has occurred. In the case of a basic program, it has ten 0xD3 characters followed by a 6 character filename. If the filename is less than 6 characters it is padded with zeros. Then there is a idle area that is pure mark (no frames) and finally the program data. I suspect this period of idle is to allow the computer time to decide if it wants to load the program based on the filename, etc. At the end of the program data there are usually 19 zeros followed by more idle/mark (lead out). The only theory I have for "end of transmission" is that it requires BOTH zeros and a period of idle (the lead out). There is an example demo program called "rag" that has 3 zeros followed by idle that doesn't trigger an end of transmission, but it may not be looking for that in the filename part of the transmission. So it may be that it requires (1) data part of transmission, (2) a number of zeros, and (3) idle area (lead out). This could be tested to figure it out.

The way that the WAV builder in nec.c works though is that it is looking for a zero to move from stage 0 (filename?) to stage 1 (data?). Technically for stage 0 it should look for the 0xD3 values and count out 6 bytes of filename after the last 0xD3, then provide an appropriate amount of idle area. The stage 1 puzzles me because it is looking for 3 zeros (which with the 19 zeros I am seeing at the end of example programs, might be 3 real zero bytes to tell basic there are no more lines and 16 zero bytes to setup for the end the transmission). What the stage 1 testing does it notice the 3 zeros (which may or may not be in the header/loader stub or the machine code generated!!!! This is NOT BASIC!) and then insert an idle period after them before moving to stage 2 which isn't addressed further.

My advice for modification is to:

Modify the stage 0 testing to look for 0xD3's and count out 6 filename characters, then do the idle period as it currently does.
Eliminate the stage 1 completely.
Write the data just as it is until complete.
Then write 16 zeros to prepare for end of transmission.
Then write the idle lead out.

I believe there is a p6 to WAV converter I saw on a Japanese website, but I didn't download and will have to find it. It may be designed for BASIC code only and I don't know if there is any source code for it or not. There are commands to save data to the cassette interface so I may try sending some data including lots of zeros to see what it does.
stefano wrote:..please try changing "period0 = 21;" to 22 (or 23). It just "sounds" better, but sometimes an ear tuning suffices, let's remember that the tape speed couldn't be perfect in any case ;)
There is an option on the computer to change the baud rate between 600 and 1200 by poking a value, maybe even in between (900?).

How do you get setup to compile z88dk on windows? Is there a link/guide to do this?

Thanks,

Alan
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

alank2 wrote:How do you get setup to compile z88dk on windows? Is there a link/guide to do this?
You can use msys2 or cygwin to do it the same way as linux. I've compiled z88dk using msys2 and then used the install from native windows, setting up the environment as usual for windows (PATH, ZCCCFG).

But for working on the z88dk binaries, I use vs2015. You can double-click on z88dk/win32/z88dk.sln to open the project in visual studio. Make sure you're set to produce the release build and go.

You cannot actually build the classic z80 libraries from native windows (that does require msys or cygwin) but that will only matter if you want to change the classic z80 source code.
stefano
Well known member
Posts: 2137
Joined: Mon Jul 16, 2007 7:39 pm

Post by stefano »

Alan,
I know, for my personal experience that the whole z88dk build process (libraries included) can be tricky, the first times. One of the reasons is the many ways you can get it (compilers, build tools, IDE variants, etc).. but the single appmake component should be easy to compile.

You need config.h to be created in {z88dk}/src:

#define WIN32 1
#define Z88DK_VERSION "[Alvin_version]"


...even #define UNIX 1 could be ok, if you have the proper environment ;)


Then use something like:
gcc -o appmake -DWIN32 *.c

Or (Visual C):
cl /Feappmake -DWIN32 -D _CRT_SECURE_NO_DEPRECATE *.c


... if you have "make" then use it. It will save lots of time on the next rebuild.
appmake.exe will have to be copied into the "bin" folder.



I still need to read your email detail to propose code changes basing on your advice. I'm a little concerned on the possible differences between the PC8x and PC6x, but.. well.. nobody never gave feedback on the PC88 !

Stefano
Post Reply