const std = @import("std"); pub const vendor_command: u8 = 0x94; pub const envelope_version: u8 = 1; pub const variant_default: u8 = 0; pub const frame_header_len: usize = 4; pub const data_buffer_size: usize = 512; pub const response_buffer_size: usize = 512; pub const ok_frame = [2]u8{ vendor_command, 0x02 }; pub const failure_frame = [2]u8{ vendor_command, 0x01 }; pub const Handler = enum(u8) { gen4_script = 0x10, pic_primitive = 0x30, spitfire = 0x32, }; pub const BufferType = enum(u2) { data = 0, metadata = 1, cmdrsp = 2, sys = 3, }; pub fn header(handler: Handler) [4]u8 { return .{ envelope_version, variant_default, @intFromEnum(handler), variant_default }; } pub const FrameFlags = packed struct(u8) { id: u3 = 0, buffer_type: BufferType = .data, sof: bool = false, eof: bool = false, read: bool = false, }; pub fn frame( out: []u8, buffer_type: BufferType, id: u3, read: bool, sof: bool, eof: bool, data: []const u8, ) []u8 { std.debug.assert(out.len >= frame_header_len + data.len); const flags = FrameFlags{ .id = id, .buffer_type = buffer_type, .sof = sof, .eof = eof, .read = read, }; out[0] = vendor_command; out[1] = @bitCast(flags); out[2] = @intCast(data.len >> 8); out[3] = @intCast(data.len & 0xFF); @memcpy(out[frame_header_len .. frame_header_len + data.len], data); return out[0 .. frame_header_len + data.len]; } test "header" { try std.testing.expectEqual([4]u8{ 1, 0, 0x30, 0 }, header(.pic_primitive)); try std.testing.expectEqual([4]u8{ 1, 0, 0x10, 0 }, header(.gen4_script)); } test "frame layout" { var buf: [16]u8 = undefined; const f = frame(&buf, .cmdrsp, 0, false, true, true, &.{ 0xAA, 0xBB }); try std.testing.expectEqual(@as(usize, 6), f.len); try std.testing.expectEqual(@as(u8, 0x94), f[0]); try std.testing.expectEqual(@as(u8, 0x70), f[1]); try std.testing.expectEqual(@as(u8, 0x00), f[2]); try std.testing.expectEqual(@as(u8, 0x02), f[3]); try std.testing.expectEqual(@as(u8, 0xAA), f[4]); try std.testing.expectEqual(@as(u8, 0xBB), f[5]); } test "frame flags read metadata" { var buf: [16]u8 = undefined; const f = frame(&buf, .metadata, 3, true, true, false, &.{}); try std.testing.expectEqual(@as(u8, 0xAB), f[1]); }