Jump to content

Open Club  ·  76 members

StellaRT
IGNORED

Community-Built Unnamed 1970's Video Game Console-Compatible System (WIP)


Al_Nafuur

Recommended Posts

2 minutes ago, Al_Nafuur said:

It is indeed a "STA $FFF9" at $1000 there is a $8d -> STA, $1001 and $1002 are the address ($FFF9)

good catch :)

Do we know if these banked carts drive the bus, even if the address is a hotspot ? Because in that case we would have 2 drivers: console (or our 245 chip) and the cartridge.
What would happen if the program flow in stella ist stopping when we have this ? I feel we could have the 245 and the cartridge driving the bus for a very long time ?


 

 

 

 

 

 

 

  • Like 1
Link to comment
Share on other sites

not that specific log, but for a new one:
image.thumb.png.b76f39c2b4f7a8e8185d5823daa88690.png

Its not a specific value...you can just watch the bits set and clear in no specific order until they all have the new value.
It also depends on the loggig threshold I set. What voltage should I display as "1" and what is still "0". Currently I use 2.5V for a "1"
and it is also oscillating a bit so sometimes you see a bit set and reset before it is stable. But thats actually normal operation and is also to be seen on the real console.

Edited by Kroko
Link to comment
Share on other sites

8 minutes ago, Kroko said:

not that specific log, but for a new one:
image.thumb.png.b76f39c2b4f7a8e8185d5823daa88690.png

Its not a specific value...you can just watch the bits set and clear in no specific order until they all have the new value.
It also depends on the loggig threshold I set. What voltage should I display as "1" and what is still "0". Currently I use 2.5V for a "1"
and it is also oscillating a bit so sometimes you see a bit set and reset before it is stable. But thats actually normal operation and is also to be seen on the real console.

I can't see these longer periods in the new log. They don't always happen between the address changes. I am guessing they happen in about 0.5% to 5% of the address changes.

Link to comment
Share on other sites

1 minute ago, Kroko said:

Does this look good ?
image.thumb.png.4c0f1dd9b54f32161f6fd2f16053136d.png
 

I was expecting that we see the same data on the bus when we see the same address ?

 

No, just because DIR is directed to the cartridge I doesn't mean it is a write from the 6507. It is just for the cartridge to read what is going on between TIA, RIOT and 6507. So in your example the first access to $1FF is a read from the 6507 from the stack (RIOT) and the second access to $1FF is a write from the 6507 to the stack. Both are written to the data bus for the cartridge to potentially read them.

  • Like 1
Link to comment
Share on other sites

One difference I noticed between Stella and real console is this:
image.thumb.png.0dcfb64ca7be99a85b5da83d9f187008.png

Even if Stella outputs the same address as before, it does output 0 in between. Is there a way to not do that, at least if the address stays the same ?
To detect that there is actually nothing to do and not touch the bus is such a case ? Its probably not super important but it would bring us closer to the behavior of the real console.

  • Like 1
Link to comment
Share on other sites

3 minutes ago, Al_Nafuur said:

@Kroko

Have you added to "/boot/cmdline.txt" (cpu2 needs to be added to the isolcpus list):

isolcpus=domain,managed_irq,2,3

no I didn't. Let me try this. Please add it to the setup page ... it is easy to miss (at least for me). And maybe also the change of base address for the Pi4, so we have all setup info in that post ..

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

3 minutes ago, Kroko said:

One difference I noticed between Stella and real console is this:
image.thumb.png.0dcfb64ca7be99a85b5da83d9f187008.png

Even if Stella outputs the same address as before, it does output 0 in between. Is there a way to not do that, at least if the address stays the same ?
To detect that there is actually nothing to do and not touch the bus is such a case ? Its probably not super important but it would bring us closer to the behavior of the real console.

I didn't know the 6502 is not setting up the address "again" when it not changes.

 

I have added in my tests an extra "pause" when the address stays the same to explicitly make it two cycles for the cart. But I can switch to not touch the address bus when the address stays the same.

This will look like one "cycle" for the cartridge and might explain why the SuperCharger is not working on RTStella, because we have two "cycles" here.

 

Link to comment
Share on other sites

54 minutes ago, Kroko said:

One difference I noticed between Stella and real console is this:
image.thumb.png.0dcfb64ca7be99a85b5da83d9f187008.png

Even if Stella outputs the same address as before, it does output 0 in between. Is there a way to not do that, at least if the address stays the same ?
To detect that there is actually nothing to do and not touch the bus is such a case ? Its probably not super important but it would bring us closer to the behavior of the real console.

@Al_Nafuur Is that from your code? 

Link to comment
Share on other sites

57 minutes ago, Al_Nafuur said:

I didn't know the 6502 is not setting up the address "again" when it not changes.

 

I have added in my tests an extra "pause" when the address stays the same to explicitly make it two cycles for the cart. But I can switch to not touch the address bus when the address stays the same.

This will look like one "cycle" for the cartridge and might explain why the SuperCharger is not working on RTStella, because we have two "cycles" here.

Thanks to @Kroko's observation! Eliminating the address change in our driver when the address doesn't change between two request my modified PlusCart SC emulation is working now:

 

13 minutes ago, Thomas Jentzsch said:

@Al_Nafuur Is that from your code? 

Yes

 

  • Like 5
Link to comment
Share on other sites

1 hour ago, Kroko said:

no I didn't. Let me try this. Please add it to the setup page ... it is easy to miss (at least for me). And maybe also the change of base address for the Pi4, so we have all setup info in that post ..

I have added the information to the setup information. I have also pushed my changes to the "feature/cartridgportThread" branch on GIT. But without the modified PlusCart firmware FE and SC will (most likely) not work on your PlusCart (and on the real cartridges too).

 

I might release the firmware as beta and add your PlusCart to the beta tester group if you like, so you can update via the PlusStore.

 

There are a few changes from ZackAttack waiting to be merged to the PlusCart firmware too. @ZackAttack can you have a look my question:

https://github.com/Al-Nafuur/United-Carts-of-Atari/pull/5

 

Link to comment
Share on other sites

I think I was able to record the bus of stella after a failed bankswitch with Thomas' V3 rom. Here we try to JSR from Bank 0 to Bank 1, but stay in Bank 0:

image.thumb.png.7c2b5f9f6c9dabe856b15237693e1f81.png

Edit: was confused ... I think even though DIR is from cartridge to stella, stella should be able to see its own $D1 ...

.. maybe because of that little $00 we read something else from the bus ? Where would $B2 bring us ?

 

I would say if bit A13 is the Bank to switch to, then $B2 would mean "stay in Bank 0".


I also added a few things to the plots: NOP_Loop(23) is high from beginning to end of the NOP Loop,  Peek(22) is high whenever and as long as stella is reading from the cartridge. WaitCycleEnd is high from the beginning to the end of function WaitForCycleEnd.

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

23 minutes ago, Kroko said:

What would happen if we switch the address bus to input before we change addresses, then clear and set the new address bits while the port is input and then change direction to output ? Maybe by that we could get rid of the little $00 ..

I had thought of this before too. But as far as I understand the docs switching to input you can not set the value before switching back to output.

 

Link to comment
Share on other sites

1 minute ago, Al_Nafuur said:

I had thought of this before too. But as far as I understand the docs switching to input you can not set the value before switching back to output.

 

I read the doc such that the write will not be visible on the output until you switch direction, but the written value will take effect as soon as you switch direction ... at least some guy wrote this in some forum. Maybe we should just try it ?

Link to comment
Share on other sites

1 hour ago, Kroko said:

I read the doc such that the write will not be visible on the output until you switch direction, but the written value will take effect as soon as you switch direction ... at least some guy wrote this in some forum. Maybe we should just try it ?

 

56 minutes ago, Kroko said:

It wasn't some guy, it was the register documentation 😁  Did I misunderstand it ?

image.thumb.png.e3207e5f4b71dc0edbeb09e67c368498.png

maybe you are right, and I have misunderstood this..

seems to be worth a try..

 

Link to comment
Share on other sites

First try for "Switching it Off and On again" didin't worked:

Spoiler
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2023 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
 
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
//#include <bcm_host.h>
 
#include "M6532.hxx"
#include "TIA.hxx"
#include "System.hxx"
#include "CartPort.hxx"
 
// Peripheral base address for the Raspberry Pi3
//#define PI_PERI_BASE 0x3F000000
 
// Peripheral base address for the Raspberry Pi4
#define PI_PERI_BASE 0xFE000000
 
#define GPIO_BASE (PI_PERI_BASE + 0x200000) /* GPIO controller */
 
#define SYSTEM_TIMER_OFFSET 0x3000
#define ST_BASE (PI_PERI_BASE + SYSTEM_TIMER_OFFSET)
 
#define BLOCK_SIZE (4*1024)
// GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y)
#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
#define OUT_GPIO(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3))
#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
 
#define GPIO_SET *(gpio+7) // sets bits which are 1 ignores bits which are 0
#define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0
 
#define GET_GPIO(g) (*(gpio+13)&(1<<g)) // 0 if LOW, (1<<g) if HIGH
 
#define GET_DATA_BUS() (*(gpio+13)&0x1fe000)>>13 // GPIO 13 - 20 ( 0b000111111110000000000000 )
 
#define SET_DATA_BUS_READ() *(gpio+(1)) = 0b00000000000000000000000001001001; \
*(gpio+(2)) = 0b001000; \
GPIO_CLR = 1<<21;
#define SET_DATA_BUS_WRITE() *(gpio+(1)) = 0b00001001001001001001001001001001; \
*(gpio+(2)) = 0b001001; \
GPIO_SET = 1<<21;
 
#define GPIO_PULL *(gpio+37) // Pull up/pull down
#define GPIO_PULLCLK0 *(gpio+38) // Pull up/pull down clock
 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgePort::CartridgePort(const ByteBuffer& image, size_t size,
string_view md5, const Settings& settings,
size_t bsSize)
: CartridgeEnhanced(image, 4_KB, md5, settings, 4_KB)
{
myDirectPeek = false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgePort::install(System& system)
{
CartridgeEnhanced::install(system);
 
// cpu_set_t mask;
 
myCycleTimerThread = std::thread(&CartridgePort::cycleManagerThread, this);
 
// set CPU we want to run on
// CPU_ZERO(&mask);
// CPU_SET(2, &mask);
// int result = sched_setaffinity(0, sizeof(mask), &mask);
 
// printf("CPU set result CT %d \n", result );
 
lastAccessWasWrite = false;
 
// We need to claim all ! access to it here, and deal with it in peek/poke below
const System::PageAccess access(this, System::PageAccessType::READWRITE);
for(uInt16 addr = 0x0000; addr < 0x2000; addr += System::PAGE_SIZE)
mySystem->setPageAccess(addr, access);
 
// Set up a memory regions to access GPIO
//
/* open /dev/mem */
if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
printf("can't open /dev/mem \n");
exit(-1);
}
 
/* mmap GPIO */
gpio_map = mmap(
NULL, //Any adddress in our space will do
BLOCK_SIZE, //Map length
PROT_READ|PROT_WRITE,// Enable reading & writting to mapped memory
MAP_SHARED, //Shared with other processes
mem_fd, //File to map
GPIO_BASE //Offset to GPIO peripheral
);
 
close(mem_fd); //No need to keep mem_fd open after mmap
 
if (gpio_map == MAP_FAILED) {
printf("mmap error %d\n", (int)gpio_map);//errno also set!
exit(-1);
}
 
// Always use volatile pointer!
gpio = (volatile unsigned *)gpio_map;
 
// Set GPIO pins 0-12 to output (6502 address)
// pins 13-20 to input (6502 data)
// pin 21 to output (Level shifter direction)
*(gpio+(0)) = 0b00001001001001001001001001001001;
*(gpio+(1)) = 0b001001001;
*(gpio+(2)) = 0b001000;
 
// Set GPIO pin 21 to low (initial ls direction is read)
GPIO_CLR = 1<<21;
 
}
 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgePort::reset()
{
// printf("start reset CartridgePort\n");
 
}
 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgePort::peek(uInt16 address)
{
uInt8 result = 0;
 
if(address & 0x1000 ){ // check if cartport address
// First tell the cartridge which adress is requested
if(lastAccessWasWrite){
waitForCycleEnd();
*(gpio+(2)) = 0b001000;
GPIO_CLR = 1<<21;
}
 
*(gpio+(0)) = 0b00000000000000000000000000000000;
*(gpio+(1)) = 0b00000000000000000000000000000000;
 
GPIO_CLR = 0b1111111111111;
GPIO_SET = address;
 
*(gpio+(0)) = 0b00001001001001001001001001001001;
*(gpio+(1)) = 0b00000000000000000000000001001001;
 
cycleActive = true; //.store(true, std::memory_order_release);
waitForCycleEnd();
result = GET_DATA_BUS();
lastAccessWasWrite = false;
}else{ // TIA, RIOT or RAM read.
if(address & 0b10000000 ){
result = mySystem->m6532().peek(address);
}else{
result = mySystem->tia().peek(address);
}
// and of course we have to set the databus here for
// the Cart to peek what TIA and RIOT have to say!
setupBusForCartToRead(address, result);
}
return result;
}
 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgePort::poke(uInt16 address, uInt8 value)
{
setupBusForCartToRead(address, value);
 
if(! (address & 0x1000) ){ // check if TIA, RIOT or RAM write.
if(address & 0b10000000 ){
mySystem->m6532().poke(address, value);
}else{
mySystem->tia().poke(address, value);
}
}
return true;
}
 
void CartridgePort::setupBusForCartToRead(uInt16 address, uInt8 value){
uInt32 gpio_value = (uInt32) (address & 0x1fff) | (((uInt32)value)<<13 );
 
if(lastAccessWasWrite){
waitForCycleEnd();
}else{
*(gpio+(2)) = 0b001001;
GPIO_SET = 1<<21;
}
*(gpio+(0)) = 0b00000000000000000000000000000000;
*(gpio+(1)) = 0b00001001001001001001001000000000;
 
GPIO_CLR = 0b111111111111111111111;
GPIO_SET = gpio_value;
 
*(gpio+(0)) = 0b00001001001001001001001001001001;
*(gpio+(1)) = 0b00001001001001001001001001001001;
 
cycleActive = true;
 
lastAccessWasWrite = true;
}
 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgePort::patch(uInt16 address, uInt8 value)
{
// For now, we ignore attempts to patch the port address space
printf("start patch CartridgePort %d\n",address);
return false;
}
 
bool CartridgePort::save(Serializer& out) const
{
// For now, we ignore attempts to patch the port address space
// printf("start save CartridgePort\n");
return false;
}
bool CartridgePort::load(Serializer& in)
{
// For now, we ignore attempts to patch the port address space
// printf("start load CartridgePort\n");
return false;
}
 
void CartridgePort::cycleManagerThread() {
printf("Starting Cycle Manager\n");
int g;
cpu_set_t mask;
 
// set CPU we want to run on
CPU_ZERO(&mask);
CPU_SET(2, &mask);
int result = sched_setaffinity(0, sizeof(mask), &mask);
printf("CPU set result CM %d \n", result );
 
for(;;){
if( cycleActive == true) { //.load(std::memory_order_acquire) == true ){
// printf("Cycle start!\n" );
g = 560;
while(--g){
asm volatile("nop");
}
cycleActive = false; //.store(false, std::memory_order_release);
}
}
}
 
void CartridgePort::waitForCycleEnd() // static inline void?
{
/*
int g = 300;
while(--g){
asm volatile("nop");
}
*/
 
while( cycleActive == true ); //.load(std::memory_order_acquire) == true );
}

 

Link to comment
Share on other sites

10 hours ago, Al_Nafuur said:

 

maybe you are right, and I have misunderstood this..

seems to be worth a try..

 

8 hours ago, Al_Nafuur said:

First try for "Switching it Off and On again" didin't worked:

  Reveal hidden contents
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2023 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
 
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
//#include <bcm_host.h>
 
#include "M6532.hxx"
#include "TIA.hxx"
#include "System.hxx"
#include "CartPort.hxx"
 
// Peripheral base address for the Raspberry Pi3
//#define PI_PERI_BASE 0x3F000000
 
// Peripheral base address for the Raspberry Pi4
#define PI_PERI_BASE 0xFE000000
 
#define GPIO_BASE (PI_PERI_BASE + 0x200000) /* GPIO controller */
 
#define SYSTEM_TIMER_OFFSET 0x3000
#define ST_BASE (PI_PERI_BASE + SYSTEM_TIMER_OFFSET)
 
#define BLOCK_SIZE (4*1024)
// GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y)
#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
#define OUT_GPIO(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3))
#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
 
#define GPIO_SET *(gpio+7) // sets bits which are 1 ignores bits which are 0
#define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0
 
#define GET_GPIO(g) (*(gpio+13)&(1<<g)) // 0 if LOW, (1<<g) if HIGH
 
#define GET_DATA_BUS() (*(gpio+13)&0x1fe000)>>13 // GPIO 13 - 20 ( 0b000111111110000000000000 )
 
#define SET_DATA_BUS_READ() *(gpio+(1)) = 0b00000000000000000000000001001001; \
*(gpio+(2)) = 0b001000; \
GPIO_CLR = 1<<21;
#define SET_DATA_BUS_WRITE() *(gpio+(1)) = 0b00001001001001001001001001001001; \
*(gpio+(2)) = 0b001001; \
GPIO_SET = 1<<21;
 
#define GPIO_PULL *(gpio+37) // Pull up/pull down
#define GPIO_PULLCLK0 *(gpio+38) // Pull up/pull down clock
 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgePort::CartridgePort(const ByteBuffer& image, size_t size,
string_view md5, const Settings& settings,
size_t bsSize)
: CartridgeEnhanced(image, 4_KB, md5, settings, 4_KB)
{
myDirectPeek = false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgePort::install(System& system)
{
CartridgeEnhanced::install(system);
 
// cpu_set_t mask;
 
myCycleTimerThread = std::thread(&CartridgePort::cycleManagerThread, this);
 
// set CPU we want to run on
// CPU_ZERO(&mask);
// CPU_SET(2, &mask);
// int result = sched_setaffinity(0, sizeof(mask), &mask);
 
// printf("CPU set result CT %d \n", result );
 
lastAccessWasWrite = false;
 
// We need to claim all ! access to it here, and deal with it in peek/poke below
const System::PageAccess access(this, System::PageAccessType::READWRITE);
for(uInt16 addr = 0x0000; addr < 0x2000; addr += System::PAGE_SIZE)
mySystem->setPageAccess(addr, access);
 
// Set up a memory regions to access GPIO
//
/* open /dev/mem */
if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
printf("can't open /dev/mem \n");
exit(-1);
}
 
/* mmap GPIO */
gpio_map = mmap(
NULL, //Any adddress in our space will do
BLOCK_SIZE, //Map length
PROT_READ|PROT_WRITE,// Enable reading & writting to mapped memory
MAP_SHARED, //Shared with other processes
mem_fd, //File to map
GPIO_BASE //Offset to GPIO peripheral
);
 
close(mem_fd); //No need to keep mem_fd open after mmap
 
if (gpio_map == MAP_FAILED) {
printf("mmap error %d\n", (int)gpio_map);//errno also set!
exit(-1);
}
 
// Always use volatile pointer!
gpio = (volatile unsigned *)gpio_map;
 
// Set GPIO pins 0-12 to output (6502 address)
// pins 13-20 to input (6502 data)
// pin 21 to output (Level shifter direction)
*(gpio+(0)) = 0b00001001001001001001001001001001;
*(gpio+(1)) = 0b001001001;
*(gpio+(2)) = 0b001000;
 
// Set GPIO pin 21 to low (initial ls direction is read)
GPIO_CLR = 1<<21;
 
}
 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgePort::reset()
{
// printf("start reset CartridgePort\n");
 
}
 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgePort::peek(uInt16 address)
{
uInt8 result = 0;
 
if(address & 0x1000 ){ // check if cartport address
// First tell the cartridge which adress is requested
if(lastAccessWasWrite){
waitForCycleEnd();
*(gpio+(2)) = 0b001000;
GPIO_CLR = 1<<21;
}
 
*(gpio+(0)) = 0b00000000000000000000000000000000;
*(gpio+(1)) = 0b00000000000000000000000000000000;
 
GPIO_CLR = 0b1111111111111;
GPIO_SET = address;
 
*(gpio+(0)) = 0b00001001001001001001001001001001;
*(gpio+(1)) = 0b00000000000000000000000001001001;
 
cycleActive = true; //.store(true, std::memory_order_release);
waitForCycleEnd();
result = GET_DATA_BUS();
lastAccessWasWrite = false;
}else{ // TIA, RIOT or RAM read.
if(address & 0b10000000 ){
result = mySystem->m6532().peek(address);
}else{
result = mySystem->tia().peek(address);
}
// and of course we have to set the databus here for
// the Cart to peek what TIA and RIOT have to say!
setupBusForCartToRead(address, result);
}
return result;
}
 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgePort::poke(uInt16 address, uInt8 value)
{
setupBusForCartToRead(address, value);
 
if(! (address & 0x1000) ){ // check if TIA, RIOT or RAM write.
if(address & 0b10000000 ){
mySystem->m6532().poke(address, value);
}else{
mySystem->tia().poke(address, value);
}
}
return true;
}
 
void CartridgePort::setupBusForCartToRead(uInt16 address, uInt8 value){
uInt32 gpio_value = (uInt32) (address & 0x1fff) | (((uInt32)value)<<13 );
 
if(lastAccessWasWrite){
waitForCycleEnd();
}else{
*(gpio+(2)) = 0b001001;
GPIO_SET = 1<<21;
}
*(gpio+(0)) = 0b00000000000000000000000000000000;
*(gpio+(1)) = 0b00001001001001001001001000000000;
 
GPIO_CLR = 0b111111111111111111111;
GPIO_SET = gpio_value;
 
*(gpio+(0)) = 0b00001001001001001001001001001001;
*(gpio+(1)) = 0b00001001001001001001001001001001;
 
cycleActive = true;
 
lastAccessWasWrite = true;
}
 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgePort::patch(uInt16 address, uInt8 value)
{
// For now, we ignore attempts to patch the port address space
printf("start patch CartridgePort %d\n",address);
return false;
}
 
bool CartridgePort::save(Serializer& out) const
{
// For now, we ignore attempts to patch the port address space
// printf("start save CartridgePort\n");
return false;
}
bool CartridgePort::load(Serializer& in)
{
// For now, we ignore attempts to patch the port address space
// printf("start load CartridgePort\n");
return false;
}
 
void CartridgePort::cycleManagerThread() {
printf("Starting Cycle Manager\n");
int g;
cpu_set_t mask;
 
// set CPU we want to run on
CPU_ZERO(&mask);
CPU_SET(2, &mask);
int result = sched_setaffinity(0, sizeof(mask), &mask);
printf("CPU set result CM %d \n", result );
 
for(;;){
if( cycleActive == true) { //.load(std::memory_order_acquire) == true ){
// printf("Cycle start!\n" );
g = 560;
while(--g){
asm volatile("nop");
}
cycleActive = false; //.store(false, std::memory_order_release);
}
}
}
 
void CartridgePort::waitForCycleEnd() // static inline void?
{
/*
int g = 300;
while(--g){
asm volatile("nop");
}
*/
 
while( cycleActive == true ); //.load(std::memory_order_acquire) == true );
}

 

Clearing and setting the output values of a GPIO while it is in input mode is possible. Unfortunately we need two steps to switch the address bus direction.

 

Link to comment
Share on other sites

4 hours ago, Al_Nafuur said:

Clearing and setting the output values of a GPIO while it is in input mode is possible. Unfortunately we need two steps to switch the address bus direction.

which probably makes it worse than before :( Maybe we really need hardware latches for the address bus. And have to spend another GPIO ...

  • Like 1
Link to comment
Share on other sites

  • Recently Browsing   0 members

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