hardware: add rpi pico files

This commit is contained in:
Arran Ireland
2025-01-05 22:32:51 +00:00
parent a3e03d6fac
commit 23fc867ff1
6 changed files with 259 additions and 0 deletions

View File

@@ -0,0 +1,17 @@
const rt = @import("reticulum");
const microzig = @import("microzig");
const rp2 = microzig.hal;
const Self = @This();
pub fn monotonicMicros(ptr: *anyopaque) u64 {
_ = ptr;
return rp2.time.get_time_since_boot().to_us();
}
pub fn clock(self: *Self) rt.System.Clock {
return .{
.ptr = self,
.monotonicMicrosFn = monotonicMicros,
};
}

23
hardware/rpi/pico/Led.zig Normal file
View File

@@ -0,0 +1,23 @@
const std = @import("std");
const microzig = @import("microzig");
const rp2 = microzig.hal;
const Self = @This();
pin: rp2.gpio.Pin,
pub fn init(index: u6) Self {
return Self{
.pin = rp2.gpio.num(index),
};
}
pub fn setup(self: *Self) void {
self.pin.set_function(.sio);
self.pin.set_direction(.out);
self.pin.put(1);
}
pub fn toggle(self: *Self) void {
self.pin.toggle();
}

View File

@@ -0,0 +1,36 @@
const std = @import("std");
const microzig = @import("microzig");
const rp2 = microzig.hal;
const Self = @This();
const uart = rp2.uart.instance.num(0);
const baud_rate = 115200;
tx_pin: rp2.gpio.Pin,
rx_pin: rp2.gpio.Pin,
pub fn init() Self {
return Self{
.tx_pin = rp2.gpio.num(0),
.rx_pin = rp2.gpio.num(1),
};
}
pub fn setup(self: *Self) void {
switch (rp2.compatibility.cpu) {
.RP2040 => inline for (&.{ self.tx_pin, self.rx_pin }) |pin| {
pin.set_function(.uart);
},
.RP2350 => inline for (&.{ self.tx_pin, self.rx_pin }) |pin| {
pin.set_function(.uart_second);
},
}
uart.apply(.{
.baud_rate = baud_rate,
.clock_config = rp2.clock_config,
});
rp2.uart.init_logger(uart);
}

View File

@@ -0,0 +1,80 @@
// Adapted from the microzig usb_cdc example.
const std = @import("std");
const rt = @import("reticulum");
const microzig = @import("microzig");
const rp2 = microzig.hal;
const Clock = @import("Clock.zig");
const Led = @import("Led.zig");
const Uart = @import("Uart.zig");
const UsbSerial = @import("serial.zig").Usb;
pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
std.log.err("panic: {s}", .{message});
@breakpoint();
while (true) {}
}
pub const microzig_options = .{
.log_level = .debug,
.logFn = rp2.uart.logFn,
};
var heap: [16_000]u8 = .{0} ** 16_000;
pub fn main() !void {
var led = Led.init(25);
var uart = Uart.init();
var serial = UsbSerial.init();
led.setup();
uart.setup();
serial.setup();
var fba = std.heap.FixedBufferAllocator.init(&heap);
var pico_clock: Clock = .{};
var ascon = rp2.rand.Ascon.init();
const ally = fba.allocator();
var clock = pico_clock.clock();
var rng = ascon.random();
const announce = try make_announce(ally, clock, &rng);
const half_a_second = 500000;
var timestamp: u64 = clock.monotonicMicros();
while (true) {
serial.task();
const now = clock.monotonicMicros();
if (now - timestamp > half_a_second) {
timestamp = now;
led.toggle();
serial.writePacket(&announce);
}
const message = serial.read();
if (message.len > 0) {
const hash = rt.crypto.Hash.hash_data(message);
serial.writeFmt("Your message: {s} => hash {s}\n", .{ message, hash.hex() });
}
}
}
fn make_announce(ally: std.mem.Allocator, clock: rt.System.Clock, rng: *rt.System.Rng) !rt.Packet {
const identity = try rt.crypto.Identity.random(rng);
var builder = rt.endpoint.Builder.init(ally);
_ = try builder
.set_identity(identity)
.set_direction(.in)
.set_method(.single)
.set_application_name("reticulum-pico");
_ = try builder.append_aspect("test");
const endpoint = try builder.build();
var packet_factory = rt.packet.Factory.init(ally, clock, rng.*, .{});
return try packet_factory.make_announce(&endpoint, "some application data");
}

View File

@@ -0,0 +1 @@
pub const Usb = @import("serial/Usb.zig");

View File

@@ -0,0 +1,102 @@
const std = @import("std");
const rt = @import("reticulum");
const microzig = @import("microzig");
const rp2 = microzig.hal;
const Self = @This();
const UsbDevice = rp2.usb.Usb(.{});
const UsbClassDriver = rp2.usb.types.UsbClassDriver;
const CdcDriver = rp2.usb.cdc.CdcClassDriver(UsbDevice);
const DeviceConfiguration = rp2.usb.DeviceConfiguration;
const Config = struct {
const endpoint_in_1 = rp2.usb.Endpoint.to_address(1, .In);
const endpoint_in_2 = rp2.usb.Endpoint.to_address(2, .In);
const endpoint_out_2 = rp2.usb.Endpoint.to_address(2, .Out);
const config_descriptor = rp2.usb.templates.config_descriptor(1, 2, 0, descriptors_length, 0xc0, 100);
const cdc_descriptor = rp2.usb.templates.cdc_descriptor(0, 4, endpoint_in_1, 8, endpoint_out_2, endpoint_in_2, 64);
const descriptors = config_descriptor ++ cdc_descriptor;
const descriptors_length = rp2.usb.templates.config_descriptor_len + rp2.usb.templates.cdc_descriptor_len;
};
var cdc_driver: CdcDriver = .{};
var drivers = [_]UsbClassDriver{cdc_driver.driver()};
var device_configuration = DeviceConfiguration{
.device_descriptor = &.{
.descriptor_type = rp2.usb.DescType.Device,
.bcd_usb = 0x0200,
.device_class = 0xEF,
.device_subclass = 2,
.device_protocol = 1,
.max_packet_size0 = 64,
.vendor = 0x2E8A,
.product = 0x000a,
.bcd_device = 0x0100,
.manufacturer_s = 1,
.product_s = 2,
.serial_s = 0,
.num_configurations = 1,
},
.config_descriptor = &Config.descriptors,
.lang_descriptor = "\x04\x03\x09\x04", // length || string descriptor (0x03) || Engl (0x0409)
.descriptor_strings = &.{
&rp2.usb.utils.utf8ToUtf16Le("Raspberry Pi"),
&rp2.usb.utils.utf8ToUtf16Le("Pico Test Device"),
&rp2.usb.utils.utf8ToUtf16Le("someserial"),
&rp2.usb.utils.utf8ToUtf16Le("Board CDC"),
},
.drivers = &drivers,
};
pub const buffer_size = 1024;
tx_buffer: [buffer_size]u8,
rx_buffer: [buffer_size]u8,
pub fn init() Self {
return Self{
.tx_buffer = .{0} ** buffer_size,
.rx_buffer = .{0} ** buffer_size,
};
}
pub fn setup(self: *Self) void {
_ = self;
UsbDevice.init_clk();
UsbDevice.init_device(&device_configuration) catch unreachable;
}
pub fn task(self: *Self) void {
_ = self;
const no_debug_over_uart = false;
UsbDevice.task(no_debug_over_uart) catch unreachable;
}
pub fn writePacket(self: *Self, packet: *const rt.packet.Packet) void {
var write_buff: []const u8 = packet.write(&self.tx_buffer);
while (write_buff.len > 0) {
write_buff = cdc_driver.write(write_buff);
}
}
pub fn writeFmt(self: *Self, comptime fmt: []const u8, args: anytype) void {
const text = std.fmt.bufPrint(&self.tx_buffer, fmt, args) catch &.{};
var write_buff = text;
while (write_buff.len > 0) {
write_buff = cdc_driver.write(write_buff);
}
}
pub fn read(self: *Self) []const u8 {
var total_read: usize = 0;
var read_buff: []u8 = self.rx_buffer[0..];
while (true) {
const len = cdc_driver.read(read_buff);
read_buff = read_buff[len..];
total_read += len;
if (len == 0) break;
}
return self.rx_buffer[0..total_read];
}