Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions drivers/base/Datagram_Device.zig
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const Datagram_Device = @This();
///
/// If the implementation requires no `ptr` pointer,
/// you can safely use `undefined` here.
ptr: *anyopaque,
//ptr: *anyopaque, no more CTX prt

/// Virtual table for the datagram device functions.
vtable: *const VTable,
Expand All @@ -27,33 +27,33 @@ pub const AnyError = ConnectError || WriteError || ReadError;

/// Establishes a connection to the device (like activating a chip-select lane or similar).
/// NOTE: Call `.disconnect()` when the usage of the device is done to release it.
pub fn connect(dd: Datagram_Device) ConnectError!void {
pub fn connect(dd: *const Datagram_Device) ConnectError!void {
if (dd.vtable.connect_fn) |connectFn| {
return connectFn(dd.ptr);
return connectFn(dd);
}
}

/// Releases a device from the connection.
pub fn disconnect(dd: Datagram_Device) void {
pub fn disconnect(dd: *const Datagram_Device) void {
if (dd.vtable.disconnect_fn) |disconnectFn| {
return disconnectFn(dd.ptr);
return disconnectFn(dd);
}
}

/// Writes a single `datagram` to the device.
pub fn write(dd: Datagram_Device, datagram: []const u8) WriteError!void {
pub fn write(dd: *const Datagram_Device, datagram: []const u8) WriteError!void {
return try dd.writev(&.{datagram});
}

/// Writes multiple `datagrams` to the device.
pub fn writev(dd: Datagram_Device, datagrams: []const []const u8) WriteError!void {
pub fn writev(dd: *const Datagram_Device, datagrams: []const []const u8) WriteError!void {
const writev_fn = dd.vtable.writev_fn orelse return error.Unsupported;
return writev_fn(dd.ptr, datagrams);
return writev_fn(dd, datagrams);
}

/// Writes then reads a single `datagram` to the device.
pub fn write_then_read(
dd: Datagram_Device,
dd: *const Datagram_Device,
src: []const u8,
dst: []u8,
) (WriteError || ReadError)!void {
Expand All @@ -62,20 +62,20 @@ pub fn write_then_read(

/// Writes a slice of datagrams to the device, then reads back into another slice of datagrams
pub fn writev_then_readv(
dd: Datagram_Device,
dd: *const Datagram_Device,
write_chunks: []const []const u8,
read_chunks: []const []u8,
) (WriteError || ReadError)!void {
const writev_then_readv_fn = dd.vtable.writev_then_readv_fn orelse return error.Unsupported;
return writev_then_readv_fn(dd.ptr, write_chunks, read_chunks);
return writev_then_readv_fn(dd, write_chunks, read_chunks);
}

/// Reads a single `datagram` from the device.
/// Function returns the number of bytes written in `datagram`.
///
/// If `error.BufferOverrun` is returned, the `datagram` will still be fully filled with the data
/// that was received up till the overrun. The rest of the datagram will be discarded.
pub fn read(dd: Datagram_Device, datagram: []u8) ReadError!usize {
pub fn read(dd: *const Datagram_Device, datagram: []u8) ReadError!usize {
return try dd.readv(&.{datagram});
}

Expand All @@ -84,18 +84,18 @@ pub fn read(dd: Datagram_Device, datagram: []u8) ReadError!usize {
///
/// If `error.BufferOverrun` is returned, the `datagrams` will still be fully filled with the data
/// that was received up till the overrun. The rest of the datagram will be discarded.
pub fn readv(dd: Datagram_Device, datagrams: []const []u8) ReadError!usize {
pub fn readv(dd: *const Datagram_Device, datagrams: []const []u8) ReadError!usize {
const readv_fn = dd.vtable.readv_fn orelse return error.Unsupported;
return readv_fn(dd.ptr, datagrams);
return readv_fn(dd, datagrams);
}

pub const VTable = struct {
connect_fn: ?*const fn (*anyopaque) ConnectError!void,
disconnect_fn: ?*const fn (*anyopaque) void,
writev_fn: ?*const fn (*anyopaque, datagrams: []const []const u8) WriteError!void,
readv_fn: ?*const fn (*anyopaque, datagrams: []const []u8) ReadError!usize,
connect_fn: ?*const fn (*const Datagram_Device) ConnectError!void,
disconnect_fn: ?*const fn (*const Datagram_Device) void,
writev_fn: ?*const fn (*const Datagram_Device, datagrams: []const []const u8) WriteError!void,
readv_fn: ?*const fn (*const Datagram_Device, datagrams: []const []u8) ReadError!usize,
writev_then_readv_fn: ?*const fn (
*anyopaque,
*const Datagram_Device,
write_chunks: []const []const u8,
read_chunks: []const []u8,
) (WriteError || ReadError)!void = null,
Expand Down
35 changes: 35 additions & 0 deletions drivers/base/I2C_Device.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
//!

const std = @import("std");
const Datagram = @import("Datagram_Device.zig");

/// Error is a set of errors that make sense for I2C at the protocol level
pub const Error = error{
Expand Down Expand Up @@ -66,6 +67,12 @@ pub const Address = enum(u7) {
}
};

pub const I2C_Datagram = struct {
addr: Address,
bus: *const I2C_Device,
interface: Datagram,
};

const I2C_Device = @This();

/// Pointer to the object implementing the driver.
Expand Down Expand Up @@ -117,6 +124,34 @@ pub fn readv(dev: I2C_Device, address: Address, datagrams: []const []u8) Interfa
return readv_fn(dev.ptr, address, datagrams);
}

//just a test, no error return yet
fn datagram_readv(dd: *const Datagram, datagrams: []const []u8) Datagram.ReadError!usize {
const dev: *const I2C_Datagram = @alignCast(@fieldParentPtr("interface", dd));
return dev.bus.readv(dev.addr, datagrams) catch Datagram.ReadError.Timeout;
}

//just a test, no error return yet
fn datagram_writev(dd: *const Datagram, datagrams: []const []const u8) Datagram.WriteError!void {
const dev: *const I2C_Datagram = @alignCast(@fieldParentPtr("interface", dd));
dev.bus.writev(dev.addr, datagrams) catch {};
}

pub fn Datagram_Device(dev: *const I2C_Device, addr: Address) I2C_Datagram {
return I2C_Datagram{
.bus = dev,
.addr = addr,
.interface = Datagram{ .vtable = &Datagram_Vtable },
};
}

const Datagram_Vtable = Datagram.VTable{
.connect_fn = null,
.disconnect_fn = null,
.writev_then_readv_fn = null,
.readv_fn = datagram_readv,
.writev_fn = datagram_writev,
};

pub const VTable = struct {
writev_fn: ?*const fn (*anyopaque, Address, datagrams: []const []const u8) InterfaceError!void,
readv_fn: ?*const fn (*anyopaque, Address, datagrams: []const []u8) InterfaceError!usize,
Expand Down
1 change: 1 addition & 0 deletions examples/raspberrypi/rp2xxx/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub fn build(b: *std.Build) void {
.{ .target = raspberrypi.pico, .name = "pico_multicore", .file = "src/rp2040_only/blinky_core1.zig" },
.{ .target = raspberrypi.pico, .name = "pico_hd44780", .file = "src/rp2040_only/hd44780.zig" },
.{ .target = raspberrypi.pico, .name = "pico_pcf8574", .file = "src/rp2040_only/pcf8574.zig" },
.{ .target = raspberrypi.pico, .name = "pico_i2_test", .file = "src/rp2040_only/i2c_test.zig" },
.{ .target = raspberrypi.pico, .name = "pico_i2c_slave", .file = "src/rp2040_only/i2c_slave.zig" },
.{ .target = raspberrypi.pico_flashless, .name = "pico_flashless_blinky", .file = "src/blinky.zig" },
.{ .target = raspberrypi.pico2_arm_flashless, .name = "pico2_arm_flashless_blinky", .file = "src/blinky.zig" },
Expand Down
37 changes: 37 additions & 0 deletions examples/raspberrypi/rp2xxx/src/rp2040_only/i2c_test.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
const std = @import("std");
const microzig = @import("microzig");

const drivers = microzig.drivers;
const PCF8574 = drivers.IO_expander.PCF8574;
const State = drivers.base.Digital_IO.State;

const rp2040 = microzig.hal;
const i2c = rp2040.i2c;
const I2C_Device = rp2040.drivers.I2C_Device;
const gpio = rp2040.gpio;
const timer = rp2040.time;

const i2c0 = i2c.instance.num(0);

var i2c_device = I2C_Device.init(i2c0, null);

pub fn main() !void {
const scl_pin = gpio.num(5);
const sda_pin = gpio.num(4);
inline for (&.{ scl_pin, sda_pin }) |pin| {
pin.set_slew_rate(.slow);
pin.set_schmitt_trigger_enabled(true);
pin.set_function(.i2c);
}

i2c0.apply(.{
.clock_config = rp2040.clock_config,
});
const datagram_dev = i2c_device.i2c_device().Datagram_Device(@enumFromInt(0x27));
while (true) {
try datagram_dev.interface.write(&.{0b01011010});
timer.sleep_ms(500);
try datagram_dev.interface.write(&.{0b10100101});
timer.sleep_ms(500);
}
}