* This post has been updated after further work on this code*
External input/output is now working. To accomplish this, I heavily modified the read6502 routine within 6502emu.c. It may ultimately end up that this was not necessary, I still ponder if there was some small issue causing external input to not work as expected, however the below describes what works for me at present.
I connected up a 1602A display (not i2c), and executed a 6502 assembly Hello World program which printed to the screen as expected, with a small exception in that I had to delay in my assembly program after setting the data direction register.
Next I ensured I could read correct values when pulling GPIO's high or low from an external source and proceeded with testing spi from PORTA which was successful as well. For this I connected an SD card to PORTA and ran George Foot's full initialization, sending several commands then reads the first sector, printing the last byte back to the LCD, which on a FAT32 card was reported back correctly as 55AA. His example is at
https://github.com/gfoot/sdcard6502/tree/masterFrom that same repo, I then staged the SUBFOLDR/DEEPFILE.TXT file and executed the test_dumpfile.s program, which successfully found the directory, the file and printed it's contents to the LCD.
I did not have to delay in assembly when setting the data direction registers for spi, but I did have to delay in any code setting the ddr which supported a 1602A display.
With this I have confidence that those changes (though they can be improved) are at least working.
There is more work to be done. Known ones are:
As mentioned above with a 1602A display, when setting it's associated data direction register, in the 65c02 assembly I find it must have a delay afterward, else the display will miss the first few characters. This is odd because if the port is instead to speak with a SD card interface over SPI, no delay is needed. The shortest delay that worked was to simply set x to #128, decrement and loop till zero. Another option to solve this was to set a 2ms sleep in the C code when it sets the data direction register, however this is wasteful and slows things down too much while it is more efficient to code a small assembly delay for any port ddr used with a 1602A display.
Memory can be inspected for the via ports A and B, I "think" this may have worked in the original version and I will re-visit that code, however for now I have returned them in a custom way. I do need to make sure these are all returning correctly.
Below is the modified routine. I also I changed the address for getchar and putchar because I loaded Krusader / wozmon and the original addresses would interfere.
I have one additional global (I know) variable defined:
Code:
uint8_t via_latch = 0;
Then a modified read6502 as:
Code:
uint8_t read6502(uint16_t address)
{
#ifndef TESTING
// if (address == 0xf004) { // Don, update to work easily with Krusader
if (address == 0xe004)
{
int16_t ch = getchar_timeout_us(100);
if (ch == PICO_ERROR_TIMEOUT)
{
return 0;
}
return (uint8_t)ch & 0xFF;
#ifdef VIA_BASE_ADDRESS
}
// else if ((address & 0xFF00) == VIA_BASE_ADDRESS)
else if ((address & 0xFFF0) == VIA_BASE_ADDRESS)
{
// MODIFICATION PORTA
if (address == VIA_BASE_ADDRESS + 0x01) // PORTA
// MODIFICATION PORTA
{
uint8_t pin_0_value, pin_1_value, pin_2_value, pin_3_value, pin_4_value, pin_5_value, pin_6_value, pin_7_value;
uint8_t pins[] = {PIN_0, PIN_1, PIN_2, PIN_3, PIN_4, PIN_5, PIN_6, PIN_7};
via_latch = (gpio_get(PIN_7) << 7) | (gpio_get(PIN_6) << 6) | (gpio_get(PIN_5) << 5) | (gpio_get(PIN_4) << 4) | (gpio_get(PIN_3) << 3) | (gpio_get(PIN_2) << 2) | (gpio_get(PIN_1) << 1) | gpio_get(PIN_0);
}
// MODIFICATION PORTB
if (address == VIA_BASE_ADDRESS) // PORTB
{
uint8_t pin_8_value, pin_9_value, pin_10_value, pin_11_value, pin_12_value, pin_13_value, pin_14_value, pin_15_value;
uint8_t pins[] = {PIN_8, PIN_9, PIN_10, PIN_11, PIN_12, PIN_13, PIN_14, PIN_15};
via_latch = (pin_8_value << 7) | (pin_9_value << 6) | (pin_10_value << 5) | (pin_11_value << 4) | (pin_12_value << 3) | (pin_13_value << 2) | (pin_14_value << 1) | pin_15_value;
}
if (address == VIA_BASE_ADDRESS + 2) // PORTB DDRB
{
// Access the value stored at M6522_REG_DDRB
via_latch = via.pb.ddr;
}
if (address == VIA_BASE_ADDRESS + 3) // PORTA DDRA
{
// Access the value stored at M6522_REG_DDRA
via_latch = via.pa.ddr;
}
if (address == VIA_BASE_ADDRESS + 4) // T1C-L
{
via_latch = via.t1.counter & 0xff;
}
if (address == VIA_BASE_ADDRESS + 5) // T1C-H
{
via_latch = via.t1.counter >> 8;
}
if (address == VIA_BASE_ADDRESS + 6) // T1L-L
{
via_latch = via.t1.latch & 0xff;
}
if (address == VIA_BASE_ADDRESS + 7) // T1L-H
{
via_latch = via.t1.latch >> 8;
}
if (address == VIA_BASE_ADDRESS + 8) // T2C-L
{
via_latch = (uint8_t) (via.t2.counter & 0xff);
}
if (address == VIA_BASE_ADDRESS + 9) // T2C-H
{
via_latch = (uint8_t) (via.t2.counter >> 8);
}
//if (address == VIA_BASE_ADDRESS + 0xa) // SR
// {
// via_latch = via.sr); // FIX ME
// }
if (address == VIA_BASE_ADDRESS + 0xb) // ACR
{
via_latch = via.acr;
}
if (address == VIA_BASE_ADDRESS + 0xc) // PCR
{
via_latch = via.pcr;
}
if (address == VIA_BASE_ADDRESS + 0xd) // IFR
{
via_latch = via.intr.ifr;
}
if (address == VIA_BASE_ADDRESS + 0xe) // IER
{
via_latch = via.intr.ier;
}
if (address == VIA_BASE_ADDRESS + 0xf) // ORA/IRA Reg 1 but No handshake
{
via_latch = (gpio_get(PIN_7) << 7) | (gpio_get(PIN_6) << 6) | (gpio_get(PIN_5) << 5) | (gpio_get(PIN_4) << 4) | (gpio_get(PIN_3) << 3) | (gpio_get(PIN_2) << 2) | (gpio_get(PIN_1) << 1) | gpio_get(PIN_0);
}
// And in any case
//if ((address == VIA_BASE_ADDRESS + 0x01) || (address == VIA_BASE_ADDRESS))
// {
via_pins &= ~(M6522_RS_PINS | M6522_CS2); // clear RS pins - set CS2 low
// Set via RW high set selected set RS pins
via_pins |= (M6522_RW | M6522_CS1 | ((uint16_t)M6522_RS_PINS & address));
via_pins = m6522_tick(&via, via_pins);
// MODIFICATION VDATA
// Via trigrred IRQ
// uint8_t vdata = M6522_GET_DATA(via_pins);
uint8_t vdata = via_latch;
// printf("reading from VIA: %04X %02X \n", address, vdata);
// }
via_update();
// old_ticks > 0 ? old_ticks-- : 0;
return vdata;
//}
#endif
}
#endif
return mem[address];
}
jfoucher > I forked the repo and will sync my changes tomorrow. Let me know if you would be interested in pull request back to your repo ?
I'm curious if Fake6502 is open source, as well as the work you've done with 6502emu.c, etc?
Thanks