http://www.harmlesslion.com/cgi-bin/sho ... skunkboard
Tursi wrote:The source code to JCP is open and you are free to take chunks of it to handle the communication with the Jaguar.
Likewise, the Skunkboard download includes SkunkLib, an assembly language source file that includes all the functions you need for bidirectional communication with JCP. By default it does console, keyboard and file system access (read and write), but by using a custom JCP shell you can do anything you want.
The Skunkboard communication system is block based by default, but you can really do anything you want. You do have to link with the LibUSB library, but you don't need to know anything about it, it just provides an API.
I'll go into a little detail here about how the board works, how the communication works, and how you can take advantage of it.
The Skunkboard is powered by a Cypress RISC CPU designed as a USB controller. This CPU has built-in ROM for communicating packets across USB, and 16k of internal RAM. The first 4k is used by interrupt vectors, a small memory transfer utility, and work space for the GDB stub (naturally the GDB stub work area is unused when not using GDB). After this is about 2k of unused RAM, and then we start getting to the interesting area.
At $1800 and $2800 are Skunkboard's transfer buffers - this is a double-buffered system that allows the Cypress CPU to receive data from the USB port while the Jag's 68k is copying data out.
Finally, the last 2k of RAM are unused. It's possible to load and run code targetting to this CPU in this RAM. For more details you can look up the part's datasheet. A lot of this documentation, including details on the transfer protocol, is in the JCP source code, too.
Of course the transfer buffers are defined arbitrarily by JCP by extension the SkunkLib, but it's a convenient protocol that works, so we'll stay with it for now. Once your software has control in theory you could use it any way you like. Anyway, let's move on.
This 16k of Cypress RAM is special because it can be accessed by both the PC and the Jaguar at any time. It is not a part of the Jaguar memory map, instead, you access it over an HPI interface -- and this is what the Skunklib takes care of for you. Basically, this means that you write to a special address on the cartridge to set the mode. Then, you write the address on the Cypress chip you are interested in, and either read or write to a different cartridge access to actually access the Cypress RAM. if you aren't familiar with doing this - just stick to Skunklib.s. Otherwise, you can see HOW to do this in Skunklib.s.
On the PC side, reading or writing to the Cypress RAM is done with a call to the LibUSB API. The API call includes the address on the Cypress, the number of bytes you are interested in transferring, and a pointer to your buffer. It can manage about 4k maximum per block.
So how can you use it? The easiest way is to take advantage of the functions that you already have. Let's say you want to write a simple program that displays the status of the joystick on the PC. (I won't be able to build and test this code tonight, but it should give you an idea - because of that I'll keep my end simple).
Let's start on the Jaguar side. I will task you with writing the framework of the program (that is, it starts up, initializes the Jaguar correctly, sets up an OPL and interrupts to refresh it, gets into some kind of loop). Somewhere
in your init code, you have to initialize the Skunklib by calling:
As you go through your loop, call this function occasionally to read the joystick and send it to the PC:
Code: Select all
(Remember the above is not a complete program - you still need to set up your standard Jag code and then call this function every loop).
Code: Select all
Sendjoy: ; Joystick code from Atari's ReadJoypads, abbreviated movem.l d0/a0,-(sp) lea JOYSTICK,a0 move.w #$81fe,(a0) move.l (a0),d0 ; Read joypad, pause button, A button ; d0 = xxxxRLDU xxxxxxxx xxxxxxxx xxxxxxAP ; now just check the bits and set the appropriate text btst d0,24 bne .notup move.l #STR_UP,A0 bra .print .notup: btst d0,25 bne .notdown move.l #STR_DOWN,A0 bra .print .notdown: btst d0,26 bne .notleft move.l #STR_LEFT,A0 bra .print .notleft: btst d0,27 beq .finished move.l #STR_RIGHT,A0 .print: jsr skunkCONSOLEWRITE; write the string to the Skunk console jsr skunkNOP ; synchronize the two buffers (needed for rapid access) .finished: movem.l (sp)+,d0/a0 rts ; These strings include the end of line (13,10) and terminator (0) STR_UP: .dc.b 'Up',13,10,0 STR_DOWN: .dc.b 'Down',13,10,0 STR_LEFT: .dc.b 'Left',13,10,0 STR_RIGHT: .dc.b 'Right',13,10,0
Make sure to include the Skunk library in your build - the easiest way outside of a makefile or including it on the assembler line is to just use an include, like
When it is compiled and ready to run, make sure to include the JCP console with the "-c" option, like so:
Code: Select all
.phrase .include "../jcp2/jcp/skunk.s"
jcp -c myprog.cof
The console will start after the program is uploaded, and then as you move the joypad around, it should stream text on your PC. It's that easy to get arbitrary data from the Jaguar to the PC over the USB connection.
To see how to USE that arbitrary data, well, my recommendation is to look at the JCP console to see how to collects the data blocks. JCP includes support for user-defined consoles, so you can write your own tool and users can link it in. Alternately, I suppose if there's enough demand, I could add UDP support to JCP/Skunklib, to allow a simple call to access UDP services. We'll see, since I'll be deep in Skunkboards soon enough.