const std = @import("std"); const primitives = @import("primitives.zig"); const t = std.testing; const Builder = primitives.Builder; const Pins = enum(u8) { all_low = 0, clk_low_data_in = 2, clk_in_data_in = 3, clk_high_data_low = 4, clk_high_data_in = 6, }; pub const C6D16Error = error{InvalidStringLength}; pub const C6D16 = struct { b: *Builder, pub fn command(self: C6D16, cmd: u8) !void { try self.b.newElement(.write_bits_literal); try self.b.appendByte(6); try self.b.appendLe32(cmd); } pub fn payload(self: C6D16, value: u16) !void { try self.b.newElement(.write_bits_literal); try self.b.appendByte(16); try self.b.appendLe32(@as(u32, value) << 1); } pub fn write32BitLiteral(self: C6D16, value: u32) !void { try self.b.newElement(.write_literal_32_lsb); try self.b.appendLe32(value); } pub fn writeStringLiteral(self: C6D16, characters: []const u8) !void { if (characters.len != 4) return error.InvalidStringLength; var value: u32 = 0; var i: usize = characters.len; while (i > 0) { i -= 1; value <<= 8; value += characters[i]; } try self.write32BitLiteral(value); } pub fn writeDataWord(self: C6D16) !void { try self.b.newElement(.p16f_write_loc_buffer); } pub fn readDataWord(self: C6D16) !void { try self.b.newElement(.p16f_read_loc_buffer); } pub fn setSpeed(self: C6D16, period_ns: u32) !void { try self.b.newElement(.set_speed); try self.b.appendLe32(period_ns); } }; pub const Hw = struct { b: *primitives.Builder, pub fn setMclrHigh(self: Hw) !void { try self.b.newElement(.set_vpp_on); } pub fn setMclrLow(self: Hw) !void { try self.b.newElement(.set_vpp_off); } pub fn setClkHi(self: Hw) !void { try self.b.newElement(.set_clk_hi); } pub fn setClkLo(self: Hw) !void { try self.b.newElement(.set_clk_lo); } pub fn setPins(self: Hw, value: Pins) !void { try self.b.newElement(.set_icsp_pins); try self.b.appendByte(@intFromEnum(value) & 0xFF); } }; pub const Board = struct { b: *primitives.Builder, pub fn delayMs(self: Board, milli_seconds: u16) !void { try self.b.newElement(.delay_ms); try self.b.appendLe16(milli_seconds); } pub fn delayUs(self: Board, micro_seconds: u16) !void { try self.b.newElement(.delay_us); try self.b.appendLe16(micro_seconds); } }; test "c6d16 command element" { var b = primitives.Builder.init(std.testing.allocator); defer b.deinit(); const prog = C6D16{ .b = &b }; try prog.command(0x06); try std.testing.expectEqualSlices(u8, &.{ 0xB5, 6, 0x06, 0, 0, 0 }, b.elements()[0]); } test "c6d16 payload shifts left" { var b = primitives.Builder.init(std.testing.allocator); defer b.deinit(); const prog = C6D16{ .b = &b }; try prog.payload(0x1234); try std.testing.expectEqualSlices(u8, &.{ 0xB5, 16, 0x68, 0x24, 0, 0 }, b.elements()[0]); } test "c6d16 write string literal" { var b = primitives.Builder.init(std.testing.allocator); defer b.deinit(); const prog = C6D16{ .b = &b }; try prog.writeStringLiteral("PHCM"); try std.testing.expectEqualSlices(u8, &.{ 0xB4, 0x50, 0x48, 0x43, 0x4D }, b.elements()[0]); try std.testing.expectError(error.InvalidStringLength, prog.writeStringLiteral("MCH")); } test "hw and board generators" { var b = primitives.Builder.init(std.testing.allocator); defer b.deinit(); const hw = Hw{ .b = &b }; const board = Board{ .b = &b }; try hw.setMclrHigh(); try board.delayMs(100); try hw.setPins(.all_low); try hw.setMclrLow(); try board.delayUs(250); const els = b.elements(); try std.testing.expectEqualSlices(u8, &.{0xB0}, els[0]); try std.testing.expectEqualSlices(u8, &.{ 0x94, 100, 0 }, els[1]); try std.testing.expectEqualSlices(u8, &.{ 0xB2, 0 }, els[2]); try std.testing.expectEqualSlices(u8, &.{0xB1}, els[3]); try std.testing.expectEqualSlices(u8, &.{ 0xA0, 250, 0 }, els[4]); }