diff --git a/src/main.zig b/src/main.zig index bfb5127..e619da2 100644 --- a/src/main.zig +++ b/src/main.zig @@ -222,8 +222,6 @@ pub const Circuit = struct { const UpdateOrder = []*Component; }; -var null_signal = Signal{}; - pub const Component = struct { name: []const u8, @@ -402,6 +400,77 @@ pub const Microchip = struct { } }; +pub const Node = struct { + component: Component, + + pub fn init(allocator: std.mem.Allocator) !*Node { + var self = try allocator.create(Node); + errdefer allocator.destroy(self); + try Component.init(&self.component, allocator, "Circuit Node", 2, 1, &update, &deinit); + return self; + } + + pub fn deinit(component: *Component, allocator: std.mem.Allocator) void { + const self: *Node = @fieldParentPtr("component", component); + allocator.destroy(self); + } + + pub fn update(component: *Component) AllocatorError!void { + const output = component.getOutput(0); + const activate = component.getInput(0) orelse &Signal{ .digital = 1 }; + const trigger = component.getInput(1) orelse &Signal{}; + + if (activate.digital == 0) { + output.digital = 0; + output.analog = 0.0; + } else { + output.digital = trigger.digital; + output.analog = trigger.analog; + } + } +}; + +test "Node" { + var trigger = Signal{ .digital = 1, .analog = 1.0 }; + var activate = Signal{}; + + var node = try Node.init(std.testing.allocator); + defer node.component.deinit(std.testing.allocator); + node.component.inputs.items[1].signal = &trigger; + + // should always pass trigger signal if activate is disconnected + try node.component.update(); + try std.testing.expectEqual(Signal{ .digital = 1, .analog = 1.0 }, node.component.getOutput(0).*); + + node.component.inputs.items[0].signal = &activate; + + // should not pass trigger signal if activate is 0 + activate.digital = 0; + activate.analog = 0.0; + try node.component.update(); + try std.testing.expectEqual(Signal{ .digital = 0, .analog = 0.0 }, node.component.getOutput(0).*); + + // should pass trigger signal if activate is 1 ... + activate.digital = 1; + activate.analog = 0.0; + try node.component.update(); + try std.testing.expectEqual(Signal{ .digital = 1, .analog = 1.0 }, node.component.getOutput(0).*); + + // should not pass trigger signal if activate.digital is 0 + // even if activate.analog is not 0.0 + activate.digital = 0; + activate.analog = 1.0; + try node.component.update(); + try std.testing.expectEqual(Signal{ .digital = 0, .analog = 0.0 }, node.component.getOutput(0).*); + + // should preserve the trigger signal polarity and analog strength + activate.digital = 1; + trigger.digital = -1; + trigger.analog = -0.69; + try node.component.update(); + try std.testing.expectEqual(Signal{ .digital = -1, .analog = -0.69 }, node.component.getOutput(0).*); +} + pub const Battery = struct { component: Component,