109 lines
3.3 KiB
C
109 lines
3.3 KiB
C
#include <stdint.h>
|
|
#include <stdio.h>
|
|
|
|
#include "pico/stdlib.h"
|
|
#include "pico/multicore.h"
|
|
#include "hardware/pio.h"
|
|
|
|
#include "core_comm.h"
|
|
#include "z80_bus.pio.h"
|
|
|
|
#define Z80_PIO pio1
|
|
#define Z80_MONITOR_SM 0
|
|
|
|
#define Z80_OE_PIN 0
|
|
#define Z80_DIR_PIN 1
|
|
#define Z80_DATA_PIN 2
|
|
#define Z80_DATA_WIDTH 8
|
|
#define Z80_IOREQ_PIN 10
|
|
#define Z80_RD_PIN 11
|
|
#define Z80_CS_PIN 12
|
|
#define Z80_A0_PIN 13
|
|
#define Z80_A1_PIN 14
|
|
|
|
#define Z80_RD_MASK (1u << Z80_RD_PIN)
|
|
#define Z80_CS_MASK (1u << Z80_CS_PIN)
|
|
#define Z80_ADDR_MASK 0x3u
|
|
#define Z80_DATA_MASK 0xffu
|
|
|
|
// --------------------------------
|
|
// CORE 1
|
|
// --------------------------------
|
|
|
|
static void core1_puts(const char *s) {
|
|
while(*s){
|
|
core1_to_core0_write_blocking((uint32_t)*s);
|
|
s++;
|
|
}
|
|
}
|
|
|
|
static void z80_write_monitor_init(void) {
|
|
uint offset = pio_add_program(Z80_PIO, &z80_write_monitor_program);
|
|
|
|
// Keep the bus isolated while selecting B (Z80) -> A (Pico).
|
|
gpio_init(Z80_OE_PIN);
|
|
gpio_put(Z80_OE_PIN, 1);
|
|
gpio_set_dir(Z80_OE_PIN, GPIO_OUT);
|
|
gpio_init(Z80_DIR_PIN);
|
|
gpio_put(Z80_DIR_PIN, 0);
|
|
gpio_set_dir(Z80_DIR_PIN, GPIO_OUT);
|
|
|
|
for (uint pin = Z80_DATA_PIN; pin <= Z80_A1_PIN; pin++) {
|
|
pio_gpio_init(Z80_PIO, pin);
|
|
}
|
|
pio_sm_set_consecutive_pindirs(Z80_PIO, Z80_MONITOR_SM,
|
|
Z80_DATA_PIN,
|
|
Z80_A1_PIN - Z80_DATA_PIN + 1,
|
|
false);
|
|
|
|
pio_sm_config config = z80_write_monitor_program_get_default_config(offset);
|
|
sm_config_set_in_pins(&config, Z80_OE_PIN);
|
|
sm_config_set_in_shift(&config, false, false, 32);
|
|
pio_sm_init(Z80_PIO, Z80_MONITOR_SM, offset, &config);
|
|
pio_sm_set_enabled(Z80_PIO, Z80_MONITOR_SM, true);
|
|
|
|
// Enable only after every Pico-side data pin has become an input.
|
|
gpio_put(Z80_OE_PIN, 0);
|
|
}
|
|
|
|
void core1_entry() {
|
|
z80_write_monitor_init();
|
|
core1_puts("core 1: Z80 write monitor started\r\n");
|
|
|
|
uint64_t write_count = 0;
|
|
uint8_t last_addr = 0;
|
|
uint8_t last_data = 0;
|
|
absolute_time_t next_report = make_timeout_time_ms(100);
|
|
|
|
while (true) {
|
|
while (!pio_sm_is_rx_fifo_empty(Z80_PIO, Z80_MONITOR_SM)) {
|
|
uint32_t bus_sample = pio_sm_get(Z80_PIO, Z80_MONITOR_SM);
|
|
// Check if it is for us -> CS=1
|
|
if ((bus_sample & Z80_CS_MASK) != 0) {
|
|
uint8_t addr = (bus_sample >> Z80_A0_PIN) & Z80_ADDR_MASK;
|
|
if ((bus_sample & Z80_RD_MASK) != 0) {
|
|
// WR
|
|
last_addr = addr;
|
|
last_data = (bus_sample >> Z80_DATA_PIN) & Z80_DATA_MASK;
|
|
write_count += 1;
|
|
} else {
|
|
// RD
|
|
}
|
|
}
|
|
}
|
|
|
|
if (time_reached(next_report)) {
|
|
char message[48];
|
|
snprintf(message, sizeof(message), "Z80 writes: %llu\r\n", (unsigned long long)write_count);
|
|
core1_puts(message);
|
|
snprintf(message, sizeof(message), "Last address: %02x\r\n", last_addr);
|
|
core1_puts(message);
|
|
snprintf(message, sizeof(message), "Last data: %02x\r\n", last_data);
|
|
core1_puts(message);
|
|
next_report = make_timeout_time_ms(100);
|
|
}
|
|
|
|
tight_loop_contents();
|
|
}
|
|
}
|