Jump to content
IGNORED

PBI R:Fi - Project Design/Build Log


TangentAudio

Recommended Posts

I've had a quick skim through FJC's U1MB BIOS technical document and I've now got it in the back of my mind to perhaps try my hand at writing a plugin for configuring the WiFi device settings of the R:Fi. Would be very slick to have a U1MB menu for setting up your WiFi SSID, password, etc. Maybe it won't ultimately be flexible enough to do everything (e.g., wifi network scanning) but perhaps there are some clever ways to use things like the 'list' menu type to accomplish that.

 

http://atari8.co.uk/wp-content/uploads/2016/12/Ultimate-BIOS-Technical-Documentation.pdf

  • Like 4
Link to comment
Share on other sites

A short video showing some basic tests of enabling/disabling PBI device, reading ROM, and writing to a register to light up some LEDs.

 

 

 

Wow I love it! And if you keep posting videos like this, I might even learn how to build my own PBI device ;) :grin:

 

You are certainly making quick development progress on this project :thumbsup:

 

- Michael

  • Like 3
Link to comment
Share on other sites

Wow I love it! And if you keep posting videos like this, I might even learn how to build my own PBI device ;) :grin:

 

You are certainly making quick development progress on this project :thumbsup:

 

I'd love to be able to produce some lasting documentation on a modern approach to designing PBI devices. I'm also hoping the FPGA code that I'm developing can live on as a reusable piece for other people to make cool devices. This is why I'm sharing my process as I go, as well as all the design files and code.

 

And thanks, I'm feeling decent about the pace of progress so far. I'm a bit concerned that I will get derailled since we're finally seeing nice weather in New England. I spend most of my free time outside on mountain bikes in the nice months (and sometimes in the not-so-nice ones)... But I'm crossing my fingers that I'll still find some time in the evenings to keep this moving!

  • Like 6
Link to comment
Share on other sites

Spent a couple hours this evening getting WUDSN IDE set up and started hammering out the PBI ROM framework code. I'm using the 1985 ANTIC article as well as the Roland Scholz article as guides for the basics of setting up the table and doing the initialization. They differ somewhat in their techniques, but they're similar anyway.

 

Unfortunately, I'm a bit stumped for the evening. After a number of tries, all I can seem to get is a lockup with a black screen after booting with the XL OS, with my device asserted (I am assuming the OS wrote $D1FF with my device ID of $80 during the probe, and it's crashed somewhere in the init). I can confirm that when I boot with OS B (which has no PBI routines) and use SpartaDOS to manually assert my device and dump the ROM at $D800 that the table is there and my init code and stubbed out vectors are also there as expected.

 

I'm sure I've missed something obvious... If any PBI gurus care to take a look at the very humble beginnings and see if something jumps out, I'd greatly appreciate the extra set of eyes.

 

Here's a link to the current code (locates at $D800 in the PBI ROM):

https://github.com/tangentaudio/atari_pbi/blob/master/Atari/Handler/handler.asm

Link to comment
Share on other sites

are you sure this is a valid address?

 

NEWDEV = $E486

 

I don't see mention of it in mapping the atari.

 

Yes, it's correct (also used by the U1MB PBI BIOS for the Z: clock handler). Mapping doesn't go too deep into the PBI stuff.

 

EDIT: A point I will add is that NEWDEV supposedly has a return code, removing the need to scan HATABS looking for free entries or duplicate device names:


	ldx #'Z'
	ldy #<gendev
 	lda #>gendev
 	jsr NewDev	; returns: N = 1 - failed, C = 0 - success, C =1 - entry already exists

That's the way I'm doing it, anyway.

Edited by flashjazzcat
  • Like 1
Link to comment
Share on other sites

Just off the top of my head, but doesn't the OS need to init the device during the boot? Do you have proper init routines in your code?

 

I believe I have them in place. I have not studied the OS code directly (and probably should), but this is my understanding:

  • The XL OS scans for PBI devices at boot by cycling through each of the 8 PBI device selects ($D1FF = $01, $02, $04 ... $80 -- not sure on the order, but $80 is the PBI address I'm using for now).
  • A PBI device needs to map in some ROM, between $D800-$E031 (where the math ROM lives normally) when its device select bit is set in the select register ($D1FF), and it needs to be sure to assert /MPD so the math pack ROM is not accessed in this address space.
  • The PBI ROM between $D800-D81C is formatted as a table (shown below) - this mainly contains vectors various access functions but also the device name is stored, along with some optional checksums and identifiers
  • The XL OS code looks for a couple of signature bytes in that table that must be present for the XL OS to realize there's a PBI device present at that select address
  • If the ROM signature looks valid, the XL OS will execute the jump to the initialization vector contained in that table.
  • The initialization routine has to do a couple of things, namely setting the bit that matches the PBI select bit in DEVMASK (i.e. $80 in my case), and then storing the GENDEV address along with the device name in HATABS.
  • GENDEV is the hook in the XL OS that looks through a particular PBI device's table to find the right vector for a given operation

 

Here is my PBI table:

;-------------------------------------------------------------------------	
; PBI table (D800-D81C)
		org $D800

pbi_table	.word $BEEF		; ROM checksum - ignored
		.byte $00		; ROM revision - ignored
		.byte $80		; Signature Byte ($80)
		.byte $00		; device type
		jmp io_vector		; I/O vector
		jmp irq_vector		; IRQ vector
		.byte $91		; Signature Byte ($91)
		.byte devname		; device name (ASCII char)
					; note: all HATABS entries below are -1
		.word open_vector-1	; HATABS - open 
		.word close_vector-1	; HATABS - close
		.word get_vector-1	; HATABS - get byte
		.word put_vector-1	; HATABS - put byte
		.word status_vector-1	; HATABS - status
		.word special_vector-1	; HATABS - special
		jmp init_vector		; initialization vector
		.byte $00		; unused

are you sure this is a valid address?

 

NEWDEV = $E486

 

I don't see mention of it in mapping the atari.

 

I had exactly the same question, and looked in exactly the same place to try to find more info about it! It does appear to be a real thing based on its use in Roland Scholz's article and confirmed by Flashjazzcat by his usage of it for the clock handler.

 

To the best of my understanding that call just does the work of finding a spot in HATABS and inserting the device name and the address, and returns success or failure. The other PBI article I was following (from ANTIC in 1985) accomplishes this without the benefit of that OS function. I did try this code with no change in behavior.

; Earl Rice method (ANTIC JAN-APR 1985)
		ldx #0
search
		lda HATABS, x
		beq found	; found a spot (=0)
		inx
		inx
		inx
		cpx #36		; length of HATABS
		bcc search
		rts		; no room in HATABS
found
		lda 'R'
		sta HATABS, x
		inx
		
		lda .LO(GENDEV)
		lda .HI(GENDEV)
		sta HATABS + 2, x
Edited by TangentAudio
Link to comment
Share on other sites

 

Yes, it's correct (also used by the U1MB PBI BIOS for the Z: clock handler). Mapping doesn't go too deep into the PBI stuff.

 

EDIT: A point I will add is that NEWDEV supposedly has a return code, removing the need to scan HATABS looking for free entries or duplicate device names:


	ldx #'Z'
	ldy #<gendev
 	lda #>gendev
 	jsr NewDev	; returns: N = 1 - failed, C = 0 - success, C =1 - entry already exists

That's the way I'm doing it, anyway.

 

Great to have that confirmation, thank you. I now have a hunch that the problem I am experiencing is not one with my table or init code, but a more fundamental issue with address mapping and/or chip selects that I need to shake out. I tried inserting some good old fashioned LED debugging into my init routine, so I could see where in the init function it might be failing. The earliest spot I placed a test was just after the 3 lines of code to set the bit in DEVMASK, and it does not appear to have made it even that far.

 

Other behavior I've witnessed even before I had the ROM set up in the FPGA had shown that things go sideways when I assert my PBI device select on a system booted with the XL OS. In other words:

  • Boot XL OS + SpartaDOS X. POKE $D1FF $80 from the command line, and my device is selected but the system hangs. Could this be because SpartaDOS is using some RAM in the same range as the PBI device? Or some other type of conflict that the system doesn't appreciate given that the XL OS has PBI hooks? I've tried it with and without the U1MB/SIDE2 PBI device enabled, for what it's worth.
  • Boot OmniMon XL, which is a ROM monitor OS that I believe is based on OS B despite having "XL" in the name - and should not contain PBI support. I believe this is borne out by the U1MB/SIDE2 PBI handlers now showing up when I use OmniMon XL. I do a Select-Reboot to get into the monitor, and A D1FF 80 to enable my device. Similar behavior - my device is selected (I have an LED to tell me this), but the system hangs immediately.

So far the only "stable" method I've had for testing my FPGA is:

  • Boot OS B + SpartaDOS X. In this configuration I can POKE $D1FF $80 to my heart's content, and then PEEK, POKE or MDUMP regions of memory which map to my device and everything seems happy and functional. This is how I confirmed my ROM image appears to be in place, and it's how I've tested everything so far. However I have a feeling there's more than just the lack of PBI in OS B that's making this a 'working' configuration.

 

It occurred to me as I was lying awake at 4am that I am not currently using the EXTENB signal in my select logic in the FPGA (it's wired in but unused). I had managed to convince myself it wasn't necessary because I'm decoding the full address bus with the FPGA, but now I'm wondering if that was a poor assumption. I need to go study an XL schematic to understand what generates that signal - if it's akin to a bank select line that's controlled by a write to some register, then it could very well be the source of my woes.

Link to comment
Share on other sites

That's the way I'm doing it, anyway.

 

Can you share any pointers on your preferred tools and workflow for developing PBI handler code? Any particular ROM monitor tools or other tricks that have been particularly helpful?

 

Unfortunately I do not (yet?) have the benefit of having emulator support for this device. Of course my device is hardly doing anything at this stage, so it's probably not a huge project to try to build some basic Altirra support for testing.

Link to comment
Share on other sites

It occurred to me as I was lying awake at 4am that I am not currently using the EXTENB signal in my select logic in the FPGA (it's wired in but unused). I had managed to convince myself it wasn't necessary because I'm decoding the full address bus with the FPGA, but now I'm wondering if that was a poor assumption. I need to go study an XL schematic to understand what generates that signal - if it's akin to a bank select line that's controlled by a write to some register, then it could very well be the source of my woes.

casinh/extenb inhibits access to the internal RAM when the address is accessing the OSROM or the I/O space. This is also dependent on the PIA PORTB bits. Basically if it's asserted, a ROM or I/O access is going on. It is active low, I think.

 

Oh, important to note is that even when the OS is enabled, EXTENB is probably still deasserted during DRAM refresh, so you may need to validate MPD against EXTENB to prevent DRAM refresh issues in the RAM-under-OS in the region of D800.

 

EDIT that said, I think cas is not necesary for refresh, so it might be fine to ignore. In an fpga though? I say just validate it...

Edited by Joey Z
Link to comment
Share on other sites

also, why does your ROM extend all the way up to E031?

 

Looking at it with fresh eyes, I'm not entirely sure. I thought I had found that address in Mapping the Atari as the ending address of the math pack ROM, but now I'm seeing D800-DFFF as the math pack ROM space, which is a lot more sensible. So this definitely could be a problem if I'm stomping over 32 bytes of the charset ROM.

 

I think this stemmed from a couple nights ago when I was trying to figure out why I was only seeing the first 28 bytes of my ROM, when I realized that the memory map from the ANTIC article was a bit confusing/misleading (see below). I was only opening $D800-D81C at first, based on that table. Once I realized this error I went looking to find the top of the math pack ROM and somehow found that $E031 address and used it as the top end of my ROM address range. I can't even find a reference to it now, despite searching... Now I feel crazy.

 

post-52761-0-03546700-1492094493_thumb.png

 

Anyway I can quickly fix that this evening and see if it helps. Not sure if it'll prove to be the ultimate problem, but it can't be helping. Nice catch, thanks!

Edited by TangentAudio
Link to comment
Share on other sites

 

Looking at it with fresh eyes, I'm not entirely sure. I thought I had found that address in Mapping the Atari as the ending address of the math pack ROM, but now I'm seeing D800-DFFF as the math pack ROM space, which is a lot more sensible. So this definitely could be a problem if I'm stomping over 32 bytes of the charset ROM.

 

I think this stemmed from a couple nights ago when I was trying to figure out why I was only seeing the first 28 bytes of my ROM, when I realized that the memory map from the ANTIC article was a bit confusing/misleading (see below). I was only opening $D800-D81C at first, based on that table. Once I realized this error I went looking to find the top of the math pack ROM and somehow found that $E031 address and used it as the top end of my ROM address range. I can't even find a reference to it now, despite searching... Now I feel crazy.

 

attachicon.gifantic-memmap.PNG

 

Anyway I can quickly fix that this evening and see if it helps. Not sure if it'll prove to be the ultimate problem, but it can't be helping. Nice catch, thanks!

 

So I also noticed that you're not resetting within the HDL yet, unless git is out of date. If you're contending with the OS during boot, you could be causing the checksum to fail. Same may go for mapping the math pack out, I don't remember if that is included in the checksum or not...

  • Like 1
Link to comment
Share on other sites

 

So I also noticed that you're not resetting within the HDL yet, unless git is out of date. If you're contending with the OS during boot, you could be causing the checksum to fail. Same may go for mapping the math pack out, I don't remember if that is included in the checksum or not...

 

Github VHDL is only slightly out of date (mainly test changes from last night), but the reset logic is still not done because I've been lazy. I've been 'cheating' so far, since it gets reset after programming and power cycle. I need to do that tonight after I fix the E031 thing.

 

I think the math pack should only be mapped out if the PBI device is activated and one of the addresses in range is selected, but it's entirely possible I either got a piece of logic wrong or perhaps that ignoring EXTENB is a concern there. I need to study that a bit.

 

Definitely a few things to fix. I appreciate you taking a look at this in this much detail!

Edited by TangentAudio
Link to comment
Share on other sites

Can you share any pointers on your preferred tools and workflow for developing PBI handler code? Any particular ROM monitor tools or other tricks that have been particularly helpful?

The most important tool for my purposes was some means of flashing the (relevant parts of the) hardware's ROM without pulling the chip out of the device, and that was the necessity behind the invention of UFLASH while I was developing the PBI ROMs for the Ultimate 1MB and Incognito (long before emulation for the former was available; emulation of the latter still doesn't exist). I didn't use any monitor or debugging tools on real hardware: unfortunately it was a case of flash, observe lock-up, go back to source code. :) SIO2SD was invaluable here as well (since I was compiling direct to the target folder mounted in AspeQt/RespeQt from which UFLASH would read the flash data).

 

One very useful method, though, was writing everything as an LSIO soft-driver loaded under SDX before porting known working code to ROM. I remember tackling the rather considerable job of developing the FAT file system handler for the PBI BIOS as a soft-loaded driver, which was easier since there was no flashing involved at all. Once everything basically worked, I implemented the same code in ROM.

  • Like 1
Link to comment
Share on other sites

The most important tool for my purposes was some means of flashing the (relevant parts of the) hardware's ROM without pulling the chip out of the device, and that was the necessity behind the invention of UFLASH while I was developing the PBI ROMs for the Ultimate 1MB and Incognito (long before emulation for the former was available; emulation of the latter still doesn't exist). I didn't use any monitor or debugging tools on real hardware: unfortunately it was a case of flash, observe lock-up, go back to source code. :) SIO2SD was invaluable here as well (since I was compiling direct to the target folder mounted in AspeQt/RespeQt from which UFLASH would read the flash data).

 

One very useful method, though, was writing everything as an LSIO soft-driver loaded under SDX before porting known working code to ROM. I remember tackling the rather considerable job of developing the FAT file system handler for the PBI BIOS as a soft-loaded driver, which was easier since there was no flashing involved at all. Once everything basically worked, I implemented the same code in ROM.

 

I can at least flash the ROM in-place without too much hassle, but I do have to improve my workflow a bit. Right now it's a bit tedious and has a lot of manual steps:

  1. make changes to code (WUDSN IDE)
  2. assemble code with MADS
  3. convert XEX binary output to Intel Hex format (currently using a hex editor which happens to be able to save in Intel Hex, so this is a manual process right now)
  4. Click a menu item in Altera Quartus Prime to update the Memory Initialization File from the Intel Hex file saved above
  5. Click another menu item in Quartus Prime to start the Assembler process, which builds the programming files
  6. Shut off the Atari
  7. Open the JTAG programmer in Quartus, make sure only the User Flash Module (UFM) is selected for write/verify and start the programming. Wait about 10-15 seconds.
  8. Turn on the Atari
  9. repeat

So, nowhere near as bad as having to pull a chip and flash it in a programmer, but it could still be a lot more streamlined.

 

I've been hoping to develop the bulk of this driver using a 'soft' method as well. I was asking some questions about this on the Atari-8 programming forum a little while back. I might take a different approach and use a chunk of FPGA RAM in place of the Flash ROM. I think as long as I have the valid table from ROM in place at bootup time, I should be able to swap it out to a modified copy in FPGA RAM once booted. It will take some more thought and experimentation to see if I can get this scheme to work. I have to get the thing booting first, though. :)

Link to comment
Share on other sites

Relocatable SDX drivers can leave plenty of RAM since that DOS commonly has a low MEMLO anyway depending on the amount of memory in the system. If you need source for a skeleton LSIO driver, just let me know. It would even be easy enough to copy a fixed block of code into your PBI RAM using this method.

 

That workflow rigmarole reminds me of the early days when I was yanking the PLCC flash ROM out of the Incognito every time I changed something and reprogramming the whole 512KB just to change 12K of PBI code. It's lovely these days to just hit "assemble" in WUDSN then fire up UFLASH on real hardware and flash exactly what the assembler just spat out. :)

Edited by flashjazzcat
  • Like 1
Link to comment
Share on other sites

Relocatable SDX drivers can leave plenty of RAM since that DOS commonly has a low MEMLO anyway depending on the amount of memory in the system. If you need source for a skeleton LSIO driver, just let me know. It would even be easy enough to copy a fixed block of code into your PBI RAM using this method.

 

That workflow rigmarole reminds me of the early days when I was yanking the PLCC flash ROM out of the Incognito every time I changed something and reprogramming the whole 512KB just to change 12K of PBI code. It's lovely these days to just hit "assemble" in WUDSN then fire up UFLASH on real hardware and flash exactly what the assembler just spat out. :)

 

That skeleton driver would be quite handy, if you're willing to share it. Thanks!

Link to comment
Share on other sites

 

Github VHDL is only slightly out of date (mainly test changes from last night), but the reset logic is still not done because I've been lazy. I've been 'cheating' so far, since it gets reset after programming and power cycle.

Yes, but the issue is you have not defined, anywhere, what 'reset' means, even from power on/programming 'reset'. So it's entirely possible something is coming up asserted when it shouldn't be, or something else like that, and mapping in the ROM during boot time when it should probably be mapped out.

 

Unfortunately, it's hard for me to decipher VHDL having learned systemverilog in school, so I'm also not entirely sure your HDL is correct, although I'm not saying it isn't. I just can't tell.

 

One thing I notice is that you only seem to be updating data_dir on the rising edge of phi2. Ideally, this should be purely combinational based on the address, r/w line, and the *state* (not the edge) of phi2. Of course, doing so could violate hold times on the 6502....

 

Also, can I ask your experience/background with programmable logic, computer systems, etc.? It helps to have a reasonable understanding of where you're at in terms of what you do and don't know.

Edited by Joey Z
Link to comment
Share on other sites

Yes, but the issue is you have not defined, anywhere, what 'reset' means, even from power on/programming 'reset'. So it's entirely possible something is coming up asserted when it shouldn't be, or something else like that, and mapping in the ROM during boot time when it should probably be mapped out.

 

...

 

Also, can I ask your experience/background with programmable logic, computer systems, etc.? It helps to have a reasonable understanding of where you're at in terms of what you do and don't know.

 

No arguments there, reset should have been the first thing I did - I've only been lazy because it worked in a narrow set of circumstances which allowed me to test and build out other pieces. At least I had the decency to leave myself a note in a comment to do it. :)

 

My background and degree are in a hybrid of electrical engineering & software engineering, and I've leaned more towards the latter in terms of what I've done professionally for 20 years (these days mostly writing code for embedded Linux systems, 10-15 years ago it was more low level embedded on 8-bit and 16-bit micros). I've designed a bunch of hardware/firmware systems over the years, mostly for my own projects. I've done some CPLD designs for a few of those, for roughly similarly complex things as this (e.g., bus interface for IDE hard disk/CF card/PCMCIA card to an 8051 microcontroller, and a bank switching RAM cartridge emulator for the Atari 2600 - both of which were ~15 years ago now). This is my first FPGA design, and my first major hardware hacking project in a long time so I'm shaking the rust off as I go. I won't pretend to be an expert, but it's also far from my first rodeo in terms of hardware/firmware design and debug. I'm stronger on the software side for sure, but have always kept a toe in the hardware side.

 

This is my first foray into doing any significant hardware hacking on the Atari 8-bit or the 6502 generally, despite having Atari computers when I was a kid, from 1984-1990 or so. I got my start in the late 80s interfacing stuff to the Atari joystick ports (once I learned they could be used bidirectionally), but I had moved on to x86 PC's by the time I developed any skills to do 'serious' hardware/software projects in my later teenage years.

Link to comment
Share on other sites

Yes, but the issue is you have not defined, anywhere, what 'reset' means, even from power on/programming 'reset'. So it's entirely possible something is coming up asserted when it shouldn't be, or something else like that, and mapping in the ROM during boot time when it should probably be mapped out.

 

I'm not sure if this is strictly true in this case because I used the initialization construct for most signals and pins. My understanding is that on an FPGA this will actually bring these signals and pins up to their initialization values based on the bitstream loaded in from the FPGA's configuration flash. The initialization construct is new to me (it wasn't known practice to me from CPLD's anyway), and I didn't do much more than a cursory reading of the implications. It wasn't really my intent to rely upon that mechanism long term, but it may explain the behavior of at least appearing to mostly function without explicit reset handling.

 

From some reading it seems there are differing schools of thought over whether global reset schemes versus initializations are preferred, and that the best solution depends a lot on your FPGA, your synthesis tools, and the application. Here's one Stack Exchange post as an example: http://stackoverflow.com/questions/6363130/is-there-a-reason-to-initialize-not-reset-signals-in-vhdl-and-verilog

Link to comment
Share on other sites

just for reference, I checked in the debugger of Altirra, and the atari OS does in fact perform the checksum on the d800-DFFF region before it does any PBI register initialization, so the OS expects your device to be off at reset. That said, it goes into self test mode if the checksum doesn't work, not a black screen....

  • Like 2
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...