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.
37 /*PDx: use input, empty pin is output*/
38 #define USB_MISC_DIR IO_DIRECTION(D)
39 #define USB_MISC_PULLUP IO_OUT(D)
40 #define USB_MISC_IN IO_IN(D)
42 USB_DPLUS = 2, CPU_IRQ,
45 static inline uint8_t bit_get_negative(enum iobit_bus_control bit)
47 uint8_t ret = (1 << bit);
53 ADDRESSBUS_A0_A7_DIR = 0xff;
54 ADDRESSBUS_A0_A7_OUT = 0;
55 DATABUS_DIR = DATABUS_DIR_OUT;
56 BUS_CONTROL_DIR = bit_get_negative(VRAM_CS); //VRAM_CS is input port
57 BUS_CONTROL_OUT = BUS_CLOSE;
58 USB_MISC_DIR = (0b1100 << 4) | 0b0011; //empty pin use OUT
59 USB_MISC_PULLUP = (1 << CPU_IRQ) | (1 << VRAM_A10);
63 make phi2 edge signal, this is needed by namcot mapper and RP2C33.
69 BUS_CONTROL_OUT = BUS_CLOSE;
70 BUS_CONTROL_OUT = BUS_CLOSE ^ (1 << CPU_PHI2);
75 //for RAM adapter DRAM refresh
76 void phi2_update(void)
79 uint8_t c = BUS_CLOSE;
87 address high databus assignment
88 D0-D5: CPU and PPU A8-A13
92 static void address_set(uint16_t address)
94 ADDRESSBUS_A0_A7_OUT = address & 0xff;
95 uint8_t high = (address & 0x7fff) >> 8; //mask A0-A14
96 if((address & (1 << 13)) == 0){ //if A13 == 0
97 high |= 0x80; //set /A13
100 BUS_CONTROL_OUT = bit_get_negative(ADDRESS_HIGH_LATCH);
101 BUS_CONTROL_OUT = BUS_CLOSE;
103 static inline void direction_write(void)
105 DATABUS_DIR = DATABUS_DIR_OUT;
111 static inline void direction_read(void)
113 DATABUS_OUT = 0xff; //when input direction, pullup
114 DATABUS_DIR = DATABUS_DIR_IN;
115 asm("nop"); //wait for chaging port direction. do not remove.
119 //mmc5 ROM area need that phi2 is high
120 void cpu_read(uint16_t address, uint16_t length, uint8_t *data)
122 BUS_CONTROL_OUT = BUS_CLOSE;
124 // uint8_t c = BUS_CLOSE;
126 address_set(address);
127 if((address & 0x8000) != 0){
128 // c &= bit_get_negative(CPU_ROMCS) | (1 << CPU_ROMCS);
129 // BUS_CONTROL_OUT = c;
130 BUS_CONTROL_OUT = bit_get_negative(CPU_ROMCS);
135 BUS_CONTROL_OUT = BUS_CLOSE;
142 void cpu_read_6502(uint16_t address, uint16_t length, uint8_t *data)
146 uint8_t c = bit_get_negative(CPU_PHI2);
151 address_set(address);
152 if((address & 0x8000) != 0){
153 c &= bit_get_negative(CPU_ROMCS);
159 c |= (1 << CPU_PHI2); // | (1 << CPU_ROMCS);
176 if((address & 0x8000) != 0){
177 c &= bit_get_negative(CPU_ROMCS);
179 c &= bit_get_negative(CPU_PHI2);
189 BUS_CONTROL_OUT = BUS_CLOSE;
197 void ppu_read(uint16_t address, uint16_t length, uint8_t *data)
199 //BUS_CONTROL_OUT = BUS_CLOSE;
202 address_set(address);
203 BUS_CONTROL_OUT = bit_get_negative(PPU_RD);
207 BUS_CONTROL_OUT = BUS_CLOSE;
214 enum compare_status cpu_compare(uint16_t address, uint16_t length, const uint8_t *data)
218 enum compare_status ppu_compare(uint16_t address, uint16_t length, const uint8_t *data)
222 address_set(address);
223 BUS_CONTROL_OUT = bit_get_negative(PPU_RD);
225 if(DATABUS_IN != *data){
226 BUS_CONTROL_OUT = BUS_CLOSE;
231 BUS_CONTROL_OUT = BUS_CLOSE;
239 void cpu_write_6502_nowait(uint16_t address, uint16_t length, const uint8_t *data)
243 address_set(address);
246 control = bit_get_negative(CPU_PHI2);
247 BUS_CONTROL_OUT = control;
248 control &= bit_get_negative(CPU_RW);
249 if((address & 0x8000) != 0){
250 control &= bit_get_negative(CPU_ROMCS);
252 BUS_CONTROL_OUT = control;
255 control |= (1 << CPU_PHI2) | (1 << CPU_ROMCS);
256 BUS_CONTROL_OUT = control;
261 control &= bit_get_negative(CPU_PHI2);
262 if((address & 0x8000) != 0){
263 control &= bit_get_negative(CPU_ROMCS);
265 BUS_CONTROL_OUT = control;
268 BUS_CONTROL_OUT = BUS_CLOSE;
276 /WE controlled write operation has busconflict
280 A0-A14|-<vaild address>-
282 o is dataout, i is datain, * is bus-confilict
284 /CS controlled write operation is clean write cycle for flash memory
288 A0-A14|-<vaild address>-
291 static inline void cpu_write_flash_waveform(uint16_t address, uint8_t data)
293 uint8_t control = bit_get_negative(CPU_PHI2);
294 address_set(address);
295 if(0){ //R/W = /WE controlled write operation
296 if((address & 0x8000) != 0){
297 control &= bit_get_negative(CPU_ROMCS);
298 BUS_CONTROL_OUT = control;
300 control &= bit_get_negative(CPU_RW);
301 BUS_CONTROL_OUT = control;
303 control |= 1 << CPU_RW; //R/W close
304 BUS_CONTROL_OUT = control;
305 }else{ ///ROMCS = /CS controlled write operation
306 control &= bit_get_negative(CPU_RW);
307 BUS_CONTROL_OUT = control;
308 if((address & 0x8000) != 0){
309 control &= bit_get_negative(CPU_ROMCS);
310 BUS_CONTROL_OUT = control;
313 control |= 1 << CPU_ROMCS;
314 BUS_CONTROL_OUT = control;
316 BUS_CONTROL_OUT = BUS_CLOSE;
318 void cpu_write_flash(uint16_t address, uint16_t length, const uint8_t *data)
322 cpu_write_flash_waveform(address, *data);
329 void cpu_write_flash_order(const struct flash_order *t)
331 int length = FLASH_PROGRAM_ORDER;
334 cpu_write_flash_waveform(t->address, t->data);
341 Master clock fsc: 21.4772272 MHz
342 CPU clock fsc/12: 1.789773MHz
343 clock per second 12/fsc: 5.58*10**-7 sec, 0.55 us
345 void cpu_write_6502(uint16_t address, uint16_t length, const uint8_t *data)
349 address_set(address);
352 control = bit_get_negative(CPU_PHI2);
353 BUS_CONTROL_OUT = control;
354 control &= bit_get_negative(CPU_RW);
355 if((address & 0x8000) != 0){
356 control &= bit_get_negative(CPU_ROMCS);
358 BUS_CONTROL_OUT = control;
362 control |= (1 << CPU_PHI2); //| (1 << CPU_ROMCS);
364 BUS_CONTROL_OUT = control;
365 // DATABUS_OUT = *data;
370 control &= bit_get_negative(CPU_PHI2);
371 BUS_CONTROL_OUT = control;
372 if((address & 0x8000) != 0){
373 control &= bit_get_negative(CPU_ROMCS);
376 BUS_CONTROL_OUT = control;
380 BUS_CONTROL_OUT = BUS_CLOSE;
387 static inline void ppu_write_waveform(uint16_t address, uint8_t data)
389 address_set(address);//PPU charcter memory /CS open
390 BUS_CONTROL_OUT = bit_get_negative(PPU_WR);
392 BUS_CONTROL_OUT = BUS_CLOSE;
393 address_set(0x3fff); ///CS close, use pallete area. When address bus is 0x2000-0x2fff, some cartriges enable tilemap area.
395 void ppu_write(uint16_t address, uint16_t length, const uint8_t *data)
398 ppu_write_waveform(address, *data);
405 void ppu_write_order(const struct flash_order *t)
407 int length = FLASH_PROGRAM_ORDER;
409 ppu_write_waveform(t->address, t->data);
415 uint8_t vram_connection_get(void)
418 uint16_t address = 0x2000;
420 address_set(address);
421 ret = bit_get(USB_MISC_IN, VRAM_A10);
424 address_set(address);
425 ret |= bit_get(USB_MISC_IN, VRAM_A10) << 1;
428 address_set(address);
429 ret |= bit_get(USB_MISC_IN, VRAM_A10) << 2;
432 address_set(address);
433 ret |= bit_get(USB_MISC_IN, VRAM_A10) << 3;