Jump to content
  • entries
    652
  • comments
    2,629
  • views
    874,037

DPC+ARM - Part 7, 6507/ARM Exchange of Information

SpiceWare

1,785 views

NOTE: This blog series is obsolete.  Head on over to the Harmony/Melody Club where you'll find information on the new Linaro compiler and the new CDFJ coprocessor/bankswitch scheme that has many improvements over DPC+.

 

NOTE: I want to clarify that this is an advanced Atari 2600 programming series. As such, I will not be covering basic things like triggering a Vertical Sync, what a Kernel is, why you need to set a timer for Vertical Blank, etc. If you need to learn that you should check out with the following:

  • Collect - detailed development of a 2K game
  • 2600 Programming for Newbies - use the Sorted Table of Contents topic that's pinned at the top in order to easily access the tutorial topics in order.

 

 

Main Loop

 

We're going to start off this series with a short example of exchanging information between the 6507 and ARM. The 6507 will send the state of the left joystick to the ARM. The ARM will use that information to manipulate a color value and send it back to the 6507. That color value will be used as the initial color of a typical Atari rainbow screen.

  • 6507 reads state of left joystick and saves it in Display Data RAM
  • 6507 triggers function main() in the ARM code
  • ARM reads joystick state from Display Data RAM
  • ARM updates color value in Display Data RAM
  • ARM returns control to 6507
  • 6507 retrieves color value from Display Data RAM and uses it to generate display

The net result is that manipulating the left joystick will change the rainbow.

 

 

rainbow screen



blogentry-3056-0-10534400-1427660072_thumb.png

 

Display Data RAM

 

As mentioned in the previous entry, the 4K of Display Data RAM is used to transfer information between the 6507 and the ARM chip. In this simple program, the first 3 bytes of Display Data RAM are allocated like this:

        RORG $0000
DS_ToARM:
ARMswcha:   ds 1        ; controller state to ARM code
ARMinpt4:   ds 1        ; firebutton state to ARM code

DS_FromARM:
ARMcolubk   ds 1        ; background color from ARM code
 

These will be used as 2 data streams - the first consisting of 2 bytes, the second of just 1 byte. The first data stream is used to send data from the 6507 to the ARM. The second data stream is used to send data from the ARM to the 6507.

 

The RORG is used to set the starting address to 0, so ARMswcha is at address 0, ARMinpt4 is at 1 and ARMcolubk is at 2.

 

In the C code, which is located in custom directory, the file defines.h is used to define the same RAM locations as seen by the ARM code:

#define SWCHA   queue[0]
#define INPT4   queue[1]
#define COLUBK  queue[2]
 

queue1 is a C array that's define so that the first element is the first byte of Display Data RAM. As such, ARMswcha in the 6507 code refers to the same RAM as SWCHA in the ARM code.

 

 

6507 sending data to ARM

 

The ARM chip does not have access to the hardware within the Atari so the 6507 must obtain information, like the state of the controllers, and save it in Display Data RAM. This is done by pointing a Data Fetcher2 to the appropriate data stream, then writing those values to the stream.

 

This bit of 6507 code saves the state of the left joystick in ARMswcha and ARMinput4.

        ldx #<DS_ToARM
        stx DF0LOW
        ldx #>DS_ToARM
        stx DF0HI
        ldx SWCHA           ; read state of both joysticks
        stx DF0WRITE        ; save in ARMswcha
        ldx INPT4           ; read state of left joystick firebutton
        stx DF0WRITE        ; save in ARMinpt4 
 

 

Run ARM code

 

After the information's been saved to Display Data, the ARM code needs to be run. This is done by writing the value $FF3 to DPC+ register CALLFUNCTION:

        ldx #$FF        stx CALLFUNCTION    ; runs main() in the C code
 

At this point function main() in your C code will be run.

 

NOTE: While the ARM code is running, the DPC+ driver will put a NOP on the cartridge port's data lines in order to keep the 6507 idle. During this time the 6507's PC will be advancing thru memory, so you'll want CALLFUNCTION to be done towards the beginning of the cartridge's 4K addressing space. If CALLFUNCTION is triggered towards the end of the 4K space your program will crash if the PC wraps back to address $0000.

 

 

ARM sending/reading data from 6507

 

Unlike the 6507, which must use a data stream, the ARM chip can directly access any value in Display Data RAM. The following function, which is called by main(), will update the background color based on the current joystick state:

 

void ProcessJoystick()
{
	unsigned char color;
    unsigned char luma;
    
    if (!(INPT4 & 0x80))    // test if firebutton is held
    {
    	if (gFrame & 0x03)  // if so, abort for 3 out of 4 frames
        	return;
	}
    
    // extract current color and luma values for the background
    color   = COLUBK & 0xF0;
    luma    = COLUBK & 0x0F;
    
    if (!(SWCHA & 0x80))    // test if joystick held right
    {
    	color += 0x10;
    }
    
    if (!(SWCHA & 0x40))    // test if joystick held left
    {
    	color -= 16;
    }
    
    if (!(SWCHA & 0x20))    // test if joystick held down
    {
    	luma--;
    }
    
    if (!(SWCHA & 0x10))     // test if joystick is held up
    {
    	luma++;
    }
    
    COLUBK = color | (luma & 0x0f);}
 

 

6507 reading data from ARM

 

Once the ARM code has finished, control will be returned to the 6507. The 6507 will use a data stream to access the information generated by the ARM routines.

 

        ldx #<DS_FromARM
        stx DF0LOW
        ldx #>DS_FromARM
        stx DF0HI
        ldy DF0DATA     ; read value in ARMcolubk, Y is used in Kernel as well
        sty COLUBK      ; set the background color
 

 

Task for you

 

To help you get up to speed, I have a simple task for you - change the program to use the right joystick instead of the left.

 

After making changes to the C code, you'll compile using these steps:

  • Start up your Linux VM
  • Open a Terminal session
  • change directory to where the custom code is:
    cd /media/sf_Atari/Collect2/custom
  • optionally type make clean to remove the prior build
    make clean
  • type make to compile the code
    make

Compile C code



blogentry-3056-0-16937300-1427660077_thumb.png

Then you'll just run DASM to compile your 6507 code as normal.

 

 

 

ROM

collect2_20150329.bin

 

Source

Collect2_20150329.zip

 

1 I don't know where the name "queue" came from.

 

2 The Data Fetcher register names used in DPC+ are a misnomer because they imply read-only even though they can also be used to write data. This is because the names come from DPC (David Crane's custom coprocessor used for Pitfall II) where the only thing you could use them for was to fetch values from Display Data. In DPC+ these registers evolved to also include the ability to write to Display Data.

 

3 If you're using the DPC+ ability to generate 3-voice music you'll need to write $FE to CALLFUNCTION. This will set up an interrupt routine that causes AUDV0 to be updated once per scan line.



8 Comments


Recommended Comments

Perfect timing - I was just thinking about doing a small DPC+ARM project to get back into 2600 programming and I was struggling to remember how it all fitted together - thanks!

 

Chris

Share this comment


Link to comment

Awesome, can't wait to see your project!

 

It'll probably be 2-3 weeks before Part 8 is posted as the next 2 weeks are going to be busy - still need to do up my taxes, mom's coming for Easter weekend(dad's working in Africa), then a bunch of friends & family will be in town for the Art Car Parade.

 

After that I'm going to try to post at least 1 DPC+ARM entry a week. I'll most likely put the SF2 series on the backburner until this series is finished, they both take a lot of time to work up the entries.

Share this comment


Link to comment

Any progress on the Task for you?

 

I've started up a companion topic, DPC+ ARM Development - Task(s) for you, as I plan to continue ending each entry with a task. Please upload your work there since we can't attach them in a blog comment.

 

My hope is that what's posted will end up feeding back into the project.

Share this comment


Link to comment

Finished my taxes and mom's not coming until tomorrow, so I was able to finish and post Part 8!

Share this comment


Link to comment

I downloaded the source files, compiled the C code, and then built the ASM code with Dasm, but I didn't get the results of the posted ROM.

 

I loaded both the posted ROM and the ROM that I compiled on to my Harmony cart. The posted rom for Collect2 worked as expected, but my ROM only produced a black screen.

 

Any idea where I might have gone wrong?

 

My build environment was Rasbpian on a Pi 4 using the default GCC 8.3.0 compiler (arm-linux-gnueabihf-gcc). I did get some warnings and errors, but I worked through them by adding the "-mfpu=vfp -marm -static" flags to the Makefile.

 

5 years later, my guess is that my build environment is just too different from that described by these tutorials, but I'm hoping you might have some additional insight.

 

I'm also using the lastest version of DASM that I compiled for Raspbian.

 

Share this comment


Link to comment

The C compiler you use shouldn't matter as long as it produces the correct code for the version of the ARM used in the Harmony Cart/Melody Board.  We're not using the one documented in this blog series anymore, we're using Linaro which is covered in the Harmony/Melody Club.

 

In the Harmony/Melody Club the General topic area covers setting up the build environment, I would create a new topic there explaining that you want to set up a build environment on a Raspberry Pi. I'm not familiar with what needs to be done for that, but will ping some others that hopefully do.

 

I would also recommend using the newer CDFJ scheme rather than DPC+. It's much easier to use, and uses fewer resources that DPC+ leaving 2K more ROM and 2K more RAM available for your project. Check the CDFJ topic area for that.

 

Share this comment


Link to comment

Disregard my last post. While I wasn't able to get it to work on my Pi 4, I was able to get the build environment working on my Ryzen based system with Linux Mint and the default install of arm-none-eabi-gcc.

 

Collect 2 compiled and ran on my Harmony cart perfectly. Super easy to do.

  • Like 1

Share this comment


Link to comment
2 minutes ago, SpiceWare said:

The C compiler you use shouldn't matter as long as it produces the correct code for the version of the ARM used in the Harmony Cart/Melody Board.  We're not using the one documented in this blog series anymore, we're using Linaro which is covered in the Harmony/Melody Club.

 

In the Harmony/Melody Club the General topic area covers setting up the build environment, I would create a new topic there explaining that you want to set up a build environment on a Raspberry Pi. I'm not familiar with what needs to be done for that, but will ping some others that hopefully do.

 

I would also recommend using the newer CDFJ scheme rather than DPC+. It's much easier to use, and uses fewer resources that DPC+ leaving 2K more ROM and 2K more RAM available for your project. Check the CDFJ topic area for that.

 

I must have posted my response, just as you posted. I will head on over to the Harmony/Melody Club.

Share this comment


Link to comment
Guest
Add a comment...

×   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...