1 #include <util/delay.h>
4 #include "bus_access.h"
6 //avr/io.h use many macros, I want use IO access by inline function...
7 #define IO_DIRECTION(NAME) (DDR##NAME)
8 #define IO_OUT(NAME) (PORT##NAME)
9 #define IO_IN(NAME) (PIN##NAME)
11 connected CPU and PPU databus*/
12 #define ADDRESSBUS_A0_A7_DIR IO_DIRECTION(A)
13 #define ADDRESSBUS_A0_A7_OUT IO_OUT(A)
15 connected address high latch(HC574), CPU and PPU databus*/
16 #define DATABUS_DIR IO_DIRECTION(B)
17 #define DATABUS_OUT IO_OUT(B)
18 #define DATABUS_IN IO_IN(B)
20 DATABUS_DIR_OUT = 0xff,
23 /*PCx: output ADDRESS_HIGH_LATCH connect HC574 clock pin, bus control signal
24 VRAM_CS is input port this is design mistake!
26 #define BUS_CONTROL_DIR IO_DIRECTION(C)
27 #define BUS_CONTROL_OUT IO_OUT(C)
28 enum iobit_bus_control{
29 CPU_PHI2 = 0, CPU_ROMCS, CPU_RW,
30 RESERVE_PPU_POS_A13, PPU_RD, PPU_WR,
31 VRAM_CS, ADDRESS_HIGH_LATCH
33 //when cpu_write_flash, phi2 must be low. when phi2 is high, mmc3 and vrc4 changes bank.
35 BUS_CLOSE = ~(1 << CPU_PHI2),
36 ADDRESS_CLOSE = 0x3fff //CPU and PPU are mapped internal registers, cartridge closes buses
38 /*PDx: use input, empty pin is output*/
39 #define USB_MISC_DIR IO_DIRECTION(D)
40 #define USB_MISC_PULLUP IO_OUT(D)
41 #define USB_MISC_IN IO_IN(D)
43 USB_DPLUS = 2, CPU_IRQ,
46 static inline uint8_t bit_get_negative(enum iobit_bus_control bit)
48 uint8_t ret = (1 << bit);
53 address high databus assignment
54 D0-D5: CPU and PPU A8-A13
58 static void address_set(uint16_t address)
60 ADDRESSBUS_A0_A7_OUT = address & 0xff;
61 uint8_t high = (address & 0x7fff) >> 8; //mask A0-A14
62 if((address & (1 << 13)) == 0){ //if A13 == 0
63 high |= 0x80; //set /A13
66 BUS_CONTROL_OUT = bit_get_negative(ADDRESS_HIGH_LATCH);
67 BUS_CONTROL_OUT = BUS_CLOSE;
72 ADDRESSBUS_A0_A7_DIR = 0xff;
73 ADDRESSBUS_A0_A7_OUT = 0;
74 DATABUS_DIR = DATABUS_DIR_OUT;
75 BUS_CONTROL_DIR = bit_get_negative(VRAM_CS); //VRAM_CS is input port
76 BUS_CONTROL_OUT = BUS_CLOSE;
77 USB_MISC_DIR = (0b1100 << 4) | 0b0011; //empty pin use OUT
78 USB_MISC_PULLUP = (1 << CPU_IRQ) | (1 << VRAM_A10);
80 address_set(ADDRESS_CLOSE);
84 make phi2 edge signal, this is needed by namcot mapper and RP2C33.
90 BUS_CONTROL_OUT = BUS_CLOSE;
91 BUS_CONTROL_OUT = BUS_CLOSE ^ (1 << CPU_PHI2);
96 //for RAM adapter DRAM refresh
97 void phi2_update(void)
100 uint8_t c = BUS_CLOSE;
107 static inline void direction_write(void)
109 DATABUS_DIR = DATABUS_DIR_OUT;
115 static inline void direction_read(void)
117 DATABUS_OUT = 0xff; //when input direction, pullup
118 DATABUS_DIR = DATABUS_DIR_IN;
119 asm("nop"); //wait for chaging port direction. do not remove.
123 //mmc5 ROM area need that phi2 is high
124 void cpu_read(uint16_t address, uint16_t length, uint8_t *data)
126 BUS_CONTROL_OUT = BUS_CLOSE;
128 uint8_t c = BUS_CLOSE;
130 address_set(address);
131 if((address & 0x8000) != 0){
132 c &= bit_get_negative(CPU_ROMCS);
133 // BUS_CONTROL_OUT = c;
134 // BUS_CONTROL_OUT = bit_get_negative(CPU_ROMCS);
141 BUS_CONTROL_OUT = BUS_CLOSE;
148 void cpu_read_6502(uint16_t address, uint16_t length, uint8_t *data)
152 /* uint8_t c = bit_get_negative(CPU_PHI2);
153 BUS_CONTROL_OUT = c;*/
154 uint8_t c = BUS_CLOSE;
157 address_set(address);
162 c |= (1 << CPU_PHI2);
163 if((address & 0x8000) != 0){
164 c &= bit_get_negative(CPU_ROMCS);
174 //phi2 down, bus close
175 BUS_CONTROL_OUT = BUS_CLOSE;
180 address_set(ADDRESS_CLOSE);
183 void ppu_read(uint16_t address, uint16_t length, uint8_t *data)
185 //BUS_CONTROL_OUT = BUS_CLOSE;
188 address_set(address);
189 BUS_CONTROL_OUT = bit_get_negative(PPU_RD) & bit_get_negative(CPU_PHI2);
193 BUS_CONTROL_OUT = BUS_CLOSE;
200 enum compare_status cpu_compare(uint16_t address, uint16_t length, const uint8_t *data)
203 BUS_CONTROL_OUT = BUS_CLOSE;
205 address_set(address);
206 BUS_CONTROL_OUT = bit_get_negative(CPU_ROMCS) | (1 << CPU_PHI2);
208 if(DATABUS_IN != *data){
209 BUS_CONTROL_OUT = BUS_CLOSE;
217 BUS_CONTROL_OUT = BUS_CLOSE;
221 enum compare_status ppu_compare(uint16_t address, uint16_t length, const uint8_t *data)
225 address_set(address);
226 BUS_CONTROL_OUT = bit_get_negative(PPU_RD) & bit_get_negative(CPU_PHI2);;
228 if(DATABUS_IN != *data){
229 BUS_CONTROL_OUT = BUS_CLOSE;
234 BUS_CONTROL_OUT = BUS_CLOSE;
242 void cpu_write_6502_nowait(uint16_t address, uint16_t length, const uint8_t *data)
246 address_set(address);
249 control = bit_get_negative(CPU_RW) & bit_get_negative(CPU_PHI2);
250 BUS_CONTROL_OUT = control;
253 control |= (1 << CPU_PHI2);
254 if((address & 0x8000) != 0){
255 control &= bit_get_negative(CPU_ROMCS);
257 BUS_CONTROL_OUT = control;
264 control &= bit_get_negative(CPU_PHI2);
265 if((address & 0x8000) != 0){
266 control &= bit_get_negative(CPU_ROMCS);
268 BUS_CONTROL_OUT = control;
271 BUS_CONTROL_OUT = BUS_CLOSE;
276 address_set(ADDRESS_CLOSE);
280 /WE controlled write operation has busconflict
284 A0-A14|-<vaild address>-
286 o is dataout, i is datain, * is bus-confilict
288 /CS controlled write operation is clean write cycle for flash memory
292 A0-A14|-<vaild address>-
295 static inline void cpu_write_flash_waveform(uint16_t address, uint8_t data)
297 uint8_t control = bit_get_negative(CPU_PHI2);
298 address_set(address);
299 if(0){ //R/W = /WE controlled write operation
300 if((address & 0x8000) != 0){
301 control &= bit_get_negative(CPU_ROMCS);
302 BUS_CONTROL_OUT = control;
304 control &= bit_get_negative(CPU_RW);
305 BUS_CONTROL_OUT = control;
307 control |= 1 << CPU_RW; //R/W close
308 BUS_CONTROL_OUT = control;
309 }else{ ///ROMCS = /CS controlled write operation
310 control &= bit_get_negative(CPU_RW);
311 BUS_CONTROL_OUT = control;
312 if((address & 0x8000) != 0){
313 control &= bit_get_negative(CPU_ROMCS);
314 BUS_CONTROL_OUT = control;
317 control |= 1 << CPU_ROMCS;
318 BUS_CONTROL_OUT = control;
320 BUS_CONTROL_OUT = BUS_CLOSE;
322 void cpu_write_flash(uint16_t address, uint16_t length, const uint8_t *data)
326 cpu_write_flash_waveform(address, *data);
331 address_set(ADDRESS_CLOSE);
334 void cpu_write_flash_order(const struct flash_order *t)
336 int length = FLASH_PROGRAM_ORDER;
339 cpu_write_flash_waveform(t->address, t->data);
343 address_set(ADDRESS_CLOSE);
347 Master clock fsc: 21.4772272 MHz
348 CPU clock fsc/12: 1.789773MHz
349 clock per second 12/fsc: 5.58*10**-7 sec, 0.55 us
351 void cpu_write_6502(uint16_t address, uint16_t length, const uint8_t *data)
355 address_set(address);
358 control = bit_get_negative(CPU_RW) & bit_get_negative(CPU_PHI2);
359 BUS_CONTROL_OUT = control;
363 if((address & 0x8000) != 0){
364 control &= bit_get_negative(CPU_ROMCS);
367 control |= (1 << CPU_PHI2);
368 BUS_CONTROL_OUT = control;
375 control &= bit_get_negative(CPU_PHI2);
376 BUS_CONTROL_OUT = control;
377 if((address & 0x8000) != 0){
378 control &= bit_get_negative(CPU_ROMCS);
380 BUS_CONTROL_OUT = control;
383 BUS_CONTROL_OUT = BUS_CLOSE;
389 address_set(ADDRESS_CLOSE);
392 static inline void ppu_write_waveform(uint16_t address, uint8_t data)
394 address_set(address);//PPU charcter memory /CS open
395 BUS_CONTROL_OUT = bit_get_negative(PPU_WR) & bit_get_negative(CPU_PHI2);
397 BUS_CONTROL_OUT = BUS_CLOSE;
398 address_set(0x3fff); ///CS close, use pallete area. When address bus is 0x2000-0x2fff, some cartriges enable tilemap area.
400 void ppu_write(uint16_t address, uint16_t length, const uint8_t *data)
403 ppu_write_waveform(address, *data);
410 void ppu_write_order(const struct flash_order *t)
412 int length = FLASH_PROGRAM_ORDER;
414 ppu_write_waveform(t->address, t->data);
420 uint8_t vram_connection_get(void)
423 uint16_t address = 0x2000;
425 address_set(address);
426 ret = bit_get(USB_MISC_IN, VRAM_A10);
429 address_set(address);
430 ret |= bit_get(USB_MISC_IN, VRAM_A10) << 1;
433 address_set(address);
434 ret |= bit_get(USB_MISC_IN, VRAM_A10) << 2;
437 address_set(address);
438 ret |= bit_get(USB_MISC_IN, VRAM_A10) << 3;
444 __attribute__ ((section(".bootloader.bus")))
445 static void boot_address_set(uint16_t address)
447 ADDRESSBUS_A0_A7_OUT = address & 0xff;
448 uint8_t high = (address & 0x7fff) >> 8; //mask A0-A14
449 if((address & (1 << 13)) == 0){ //if A13 == 0
450 high |= 0x80; //set /A13
453 BUS_CONTROL_OUT = bit_get_negative(ADDRESS_HIGH_LATCH);
454 BUS_CONTROL_OUT = BUS_CLOSE;
457 __attribute__ ((section(".bootloader.bus")))
458 void mcu_programdata_read(uint16_t address, uint16_t length, uint8_t *data)
462 if(address < 0x2000){ //PPU CHR-RAM
463 boot_address_set(address);
464 BUS_CONTROL_OUT = bit_get_negative(PPU_RD) & bit_get_negative(CPU_PHI2);
468 boot_address_set(address);
469 /* if((address & 0x8000) != 0){
470 BUS_CONTROL_OUT = bit_get_negative(CPU_ROMCS);
472 BUS_CONTROL_OUT = BUS_CLOSE | (1 << CPU_PHI2);
477 BUS_CONTROL_OUT = BUS_CLOSE;
481 boot_address_set(ADDRESS_CLOSE);