Kroko Posted November 18, 2023 Share Posted November 18, 2023 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 ? 1 Link to comment Share on other sites More sharing options...
+Al_Nafuur Posted November 18, 2023 Author Share Posted November 18, 2023 I think the address area in the red circle are the issues we have with the driver having $0000 for too long on the address bus: @Kroko can you see in the logs what address and how long was on the bus in these short periods Link to comment Share on other sites More sharing options...
Kroko Posted November 18, 2023 Share Posted November 18, 2023 (edited) not that specific log, but for a new one: 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 November 18, 2023 by Kroko Link to comment Share on other sites More sharing options...
+Al_Nafuur Posted November 19, 2023 Author Share Posted November 19, 2023 8 minutes ago, Kroko said: not that specific log, but for a new one: 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 More sharing options...
Kroko Posted November 19, 2023 Share Posted November 19, 2023 Finally a log file from stella, 100MHz Thoma's test rom on PlusCart: PlusCart_FE_Test_V3_StellaEmulated_100MHz.CSV 1 Link to comment Share on other sites More sharing options...
Kroko Posted November 19, 2023 Share Posted November 19, 2023 This one is triggered on the Stack: FE_Test_V3_Pluscart_Emulated_100KHz.CSV 1 Link to comment Share on other sites More sharing options...
Kroko Posted November 19, 2023 Share Posted November 19, 2023 Does this look good ? I was expecting that we see the same data on the bus when we see the same address ? 1 Link to comment Share on other sites More sharing options...
+Al_Nafuur Posted November 19, 2023 Author Share Posted November 19, 2023 1 minute ago, Kroko said: Does this look good ? 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. 1 Link to comment Share on other sites More sharing options...
+MarcoJ Posted November 19, 2023 Share Posted November 19, 2023 12 hours ago, Al_Nafuur said: can you post a short video of the issue with the PlusCart ? Hmm, couldn't get it to repeat right now. It occurred more in the past. The Harmony also does something similar. Link to comment Share on other sites More sharing options...
Kroko Posted November 19, 2023 Share Posted November 19, 2023 One difference I noticed between Stella and real console is this: 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. 1 Link to comment Share on other sites More sharing options...
+Al_Nafuur Posted November 19, 2023 Author Share Posted November 19, 2023 @Kroko Have you added to "/boot/cmdline.txt" (cpu2 needs to be added to the isolcpus list): isolcpus=domain,managed_irq,2,3 Link to comment Share on other sites More sharing options...
Kroko Posted November 19, 2023 Share Posted November 19, 2023 (edited) 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 November 19, 2023 by Kroko 1 Link to comment Share on other sites More sharing options...
+Al_Nafuur Posted November 19, 2023 Author Share Posted November 19, 2023 3 minutes ago, Kroko said: One difference I noticed between Stella and real console is this: 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 More sharing options...
Thomas Jentzsch Posted November 19, 2023 Share Posted November 19, 2023 54 minutes ago, Kroko said: One difference I noticed between Stella and real console is this: 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 More sharing options...
+Al_Nafuur Posted November 19, 2023 Author Share Posted November 19, 2023 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 5 Link to comment Share on other sites More sharing options...
+Al_Nafuur Posted November 19, 2023 Author Share Posted November 19, 2023 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 More sharing options...
Kroko Posted November 23, 2023 Share Posted November 23, 2023 (edited) 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: 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 November 23, 2023 by Kroko 1 Link to comment Share on other sites More sharing options...
Kroko Posted November 23, 2023 Share Posted November 23, 2023 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 .. Link to comment Share on other sites More sharing options...
+Al_Nafuur Posted November 23, 2023 Author Share Posted November 23, 2023 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 More sharing options...
Kroko Posted November 23, 2023 Share Posted November 23, 2023 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 More sharing options...
Kroko Posted November 23, 2023 Share Posted November 23, 2023 (edited) It wasn't some guy, it was the register documentation 😁 Did I misunderstand it ? Edited November 23, 2023 by Kroko Link to comment Share on other sites More sharing options...
+Al_Nafuur Posted November 23, 2023 Author Share Posted November 23, 2023 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 ? maybe you are right, and I have misunderstood this.. seems to be worth a try.. Link to comment Share on other sites More sharing options...
+Al_Nafuur Posted November 24, 2023 Author Share Posted November 24, 2023 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 More sharing options...
+Al_Nafuur Posted November 24, 2023 Author Share Posted November 24, 2023 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 More sharing options...
Kroko Posted November 24, 2023 Share Posted November 24, 2023 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 ... 1 Link to comment Share on other sites More sharing options...
Recommended Posts