Skip to content

Commit

Permalink
more public function documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
floooh committed Aug 11, 2024
1 parent 09f96e7 commit b226687
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 38 deletions.
4 changes: 2 additions & 2 deletions src/chips/z80.zig
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ pub const TypeConfig = struct {
bus: type,
};

/// build a Z80 type specialized by pins-to-bus mapping and bus integer type
/// stamp out a specialized Z80 type
pub fn Type(comptime cfg: TypeConfig) type {
const Bus = cfg.bus;
return struct {
Expand Down Expand Up @@ -1192,7 +1192,7 @@ pub fn Type(comptime cfg: TypeConfig) type {
// END CONSTS

// zig fmt: off
/// execute a single Z80 clock cycle
/// execute one Z80 clock cycle
pub fn tick(self: *Self, in_bus: Bus) Bus {
@setEvalBranchQuota(4096);
var bus = in_bus & ~(CTRL | RETI);
Expand Down
18 changes: 15 additions & 3 deletions src/chips/z80ctc.zig
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,13 @@ pub const DefaultPins = Pins{
.IEIO = 23,
};

pub const TypeConfig = struct { pins: Pins, bus: type };
/// comptime type configuration for Z80 CTC
pub const TypeConfig = struct {
pins: Pins,
bus: type,
};

/// stamp out a specialized Z80CTC type
pub fn Type(comptime cfg: TypeConfig) type {
assert(cfg.pins.CS[1] == cfg.pins.CS[0] + 1);
assert(cfg.pins.ZCTO[1] == cfg.pins.ZCTO[0] + 1);
Expand All @@ -60,7 +65,7 @@ pub fn Type(comptime cfg: TypeConfig) type {
return struct {
const Self = @This();

// pin bit masks
// pin bit-masks
pub const DBUS = maskm(Bus, &cfg.pins.DBUS);
pub const D0 = mask(Bus, cfg.pins.D[0]);
pub const D1 = mask(Bus, cfg.pins.D[1]);
Expand Down Expand Up @@ -92,7 +97,7 @@ pub fn Type(comptime cfg: TypeConfig) type {
pub const RETI = mask(Bus, cfg.pins.RETI);
pub const IEIO = mask(Bus, cfg.pins.IEIO);

// control register bits
/// control register bits
pub const CTRL = struct {
pub const EI: u8 = 1 << 7; // 1: interrupts enabled, 0: interrupts disabled

Expand All @@ -117,8 +122,10 @@ pub fn Type(comptime cfg: TypeConfig) type {
pub const CONTROL: u8 = 1 << 0; // 1: control word, 0: vector
};

/// the Z80 CTC has 4 counter/timer channels
pub const NUM_CHANNELS = 4;

/// Z80 CTC channel state
pub const Channel = struct {
control: u8 = 0,
constant: u8 = 0,
Expand All @@ -134,20 +141,24 @@ pub fn Type(comptime cfg: TypeConfig) type {

chn: [NUM_CHANNELS]Channel = [_]Channel{.{}} ** NUM_CHANNELS,

/// get data bus value
pub inline fn getData(bus: Bus) u8 {
return @truncate(bus >> cfg.pins.DBUS[0]);
}

/// set data bus value
pub inline fn setData(bus: Bus, data: u8) Bus {
return (bus & ~DBUS) | (@as(Bus, data) << cfg.pins.DBUS[0]);
}

/// return an initialized Z80 CTC instance
pub fn init() Self {
var self: Self = .{};
self.reset();
return self;
}

/// reset Z80 CTC instance
pub fn reset(self: *Self) void {
for (&self.chn) |*chn| {
chn.control = CTRL.RESET;
Expand All @@ -160,6 +171,7 @@ pub fn Type(comptime cfg: TypeConfig) type {
}
}

/// execute one clock cycle
pub fn tick(self: *Self, in_bus: Bus) Bus {
var bus = in_bus;
bus = self._tick(bus);
Expand Down
8 changes: 8 additions & 0 deletions src/chips/z80irq.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const bitutils = @import("common").bitutils;
const mask = bitutils.mask;
const maskm = bitutils.maskm;

/// Z80 IRQ pin declarations
pub const Pins = struct {
DBUS: [8]comptime_int,
M1: comptime_int,
Expand All @@ -12,11 +13,13 @@ pub const Pins = struct {
IEIO: comptime_int,
};

/// Z80 IRQ comptime type configuration
pub const TypeConfig = struct {
pins: Pins,
bus: type,
};

/// stamp out a specialized Z80 IRQ type
pub fn Type(comptime cfg: TypeConfig) type {
const Bus = cfg.bus;
return struct {
Expand All @@ -41,22 +44,27 @@ pub fn Type(comptime cfg: TypeConfig) type {
return (bus & ~DBUS) | (@as(Bus, data) << cfg.pins.DBUS[0]);
}

/// reset the Z80 IRQ state
pub fn reset(self: *Self) void {
self.state = 0;
}

/// request an interrupt
pub fn request(self: *Self) void {
self.state |= NEEDED;
}

/// clear any active interrupt request
pub fn clearRequest(self: *Self) void {
self.state &= ~NEEDED;
}

/// store the 8-bit interrupt vector
pub fn setVector(self: *Self, v: u8) void {
self.vector = v;
}

/// execute one clock cycle
pub fn tick(self: *Self, in_bus: Bus) Bus {
var bus = in_bus;

Expand Down
84 changes: 51 additions & 33 deletions src/chips/z80pio.zig
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,13 @@ pub const DefaultPins = Pins{
.IEIO = 36,
};

/// Z80 PIO comptime type configuration
pub const TypeConfig = struct {
pins: Pins,
bus: type,
};

/// stamp out a specialized Z80 PIO type
pub fn Type(cfg: TypeConfig) type {
const Bus = cfg.bus;
const Z80IRQ = z80irq.Type(.{
Expand Down Expand Up @@ -107,65 +109,73 @@ pub fn Type(cfg: TypeConfig) type {
pub const PB6 = mask(Bus, cfg.pins.PB[6]);
pub const PB7 = mask(Bus, cfg.pins.PB[7]);

/// POP port A and B indices
pub const PORT = struct {
pub const A = 0;
pub const B = 1;
};
/// number of PIO ports
pub const NUM_PORTS = 2;

// Operating Modes
//
// The operating mode of a port is established by writing a control word
// to the PIO in the following format:
//
// D7 D6 D5 D4 D3 D2 D1 D0
// |M1|M0| x| x| 1| 1| 1| 1|
//
// D7,D6 are the mode word bits
// D3..D0 set to 1111 to indicate 'Set Mode'
//
/// Operating Modes
///
/// The operating mode of a port is established by writing a control word
/// to the PIO in the following format:
///
/// D7 D6 D5 D4 D3 D2 D1 D0
/// |M1|M0| x| x| 1| 1| 1| 1|
///
/// D7,D6 are the mode word bits
/// D3..D0 set to 1111 to indicate 'Set Mode'
///
pub const MODE = struct {
pub const OUTPUT: u2 = 0;
pub const INPUT: u2 = 1;
pub const BIDIRECTIONAL: u2 = 2;
pub const BITCONTROL: u2 = 3;
};

// Interrupt control word bits.
//
// D7 D6 D5 D4 D3 D2 D1 D0
// |EI|AO|HL|MF| 0| 1| 1| 1|
//
// D7 (EI) interrupt enabled (1=enabled, 0=disabled)
// D6 (AND/OR) logical operation during port monitoring (only Mode 3, AND=1, OR=0)
// D5 (HIGH/LOW) port data polarity during port monitoring (only Mode 3)
// D4 (MASK FOLLOWS) if set, the next control word are the port monitoring mask (only Mode 3)
//
// (*) if an interrupt is pending when the enable flag is set, it will then be
// enabled on the onto the CPU interrupt request line
// (*) setting bit D4 during any mode of operation will cause any pending
// interrupt to be reset
//
// The interrupt enable flip-flop of a port may be set or reset
// without modifying the rest of the interrupt control word
// by the following command:
//
// D7 D6 D5 D4 D3 D2 D1 D0
// |EI| x| x| x| 0| 0| 1| 1|
//
/// Interrupt control word bits.
///
/// D7 D6 D5 D4 D3 D2 D1 D0
/// |EI|AO|HL|MF| 0| 1| 1| 1|
///
/// D7 (EI) interrupt enabled (1=enabled, 0=disabled)
///
/// D6 (AND/OR) logical operation during port monitoring (only Mode 3, AND=1, OR=0)
///
/// D5 (HIGH/LOW) port data polarity during port monitoring (only Mode 3)
///
/// D4 (MASK FOLLOWS) if set, the next control word are the port monitoring mask (only Mode 3)
///
/// - if an interrupt is pending when the enable flag is set, it will then be
/// enabled on the onto the CPU interrupt request line
///
/// - setting bit D4 during any mode of operation will cause any pending
/// interrupt to be reset
///
/// The interrupt enable flip-flop of a port may be set or reset
/// without modifying the rest of the interrupt control word
/// by the following command:
///
/// D7 D6 D5 D4 D3 D2 D1 D0
/// |EI| x| x| x| 0| 0| 1| 1|
///
pub const INTCTRL = struct {
pub const EI: u8 = 1 << 7;
pub const ANDOR: u8 = 1 << 6;
pub const HILO: u8 = 1 << 5;
pub const MASK_FOLLOWS: u8 = 1 << 4;
};

/// type of data expected in next IO write
pub const Expect = enum {
CTRL,
IO_SELECT,
INT_MASK,
};

/// Z80 PIO port state
pub const Port = struct {
input: u8 = 0, // data input register
output: u8 = 0, // data output register
Expand All @@ -186,14 +196,17 @@ pub fn Type(cfg: TypeConfig) type {
reset_active: bool = false,
port_output_or_ioselect_dirty: bool = true,

/// get data bus value
pub inline fn getData(bus: Bus) u8 {
return @truncate(bus >> cfg.pins.DBUS[0]);
}

/// set data bus value
pub inline fn setData(bus: Bus, data: u8) Bus {
return (bus & ~DBUS) | (@as(Bus, data) << cfg.pins.DBUS[0]);
}

/// set PIO port pins value
pub inline fn setPort(comptime port: comptime_int, bus: Bus, data: u8) Bus {
return switch (port) {
PORT.A => (bus & ~PA) | (@as(Bus, data) << cfg.pins.PA[0]),
Expand All @@ -202,6 +215,7 @@ pub fn Type(cfg: TypeConfig) type {
};
}

/// get PIO port pins value
pub inline fn getPort(comptime port: comptime_int, bus: Bus) u8 {
return @truncate(bus >> switch (port) {
PORT.A => cfg.pins.PA[0],
Expand All @@ -210,12 +224,14 @@ pub fn Type(cfg: TypeConfig) type {
});
}

/// return an initialized Z80 PIO instance
pub fn init() Self {
var self: Self = .{};
self.reset();
return self;
}

/// reset Z80 PIO instance
pub fn reset(self: *Self) void {
self.reset_active = true;
self.port_output_or_ioselect_dirty = true;
Expand All @@ -233,6 +249,7 @@ pub fn Type(cfg: TypeConfig) type {
}
}

/// execute one clock cycle
pub fn tick(self: *Self, in_bus: Bus) Bus {
var bus = in_bus;
// - OUTPUT MODE: On CPU write, the bus data is written to the output
Expand Down Expand Up @@ -290,6 +307,7 @@ pub fn Type(cfg: TypeConfig) type {
self.port_output_or_ioselect_dirty = false;
return bus;
}

// new control word received from CPU
fn writeCtrl(self: *Self, p: *Port, data: u8) void {
self.reset_active = false;
Expand Down

0 comments on commit b226687

Please sign in to comment.