mirror of
https://github.com/ion232/reticulum-zig.git
synced 2025-12-22 06:37:05 +00:00
hardware: add rpi pico files
This commit is contained in:
17
hardware/rpi/pico/Clock.zig
Normal file
17
hardware/rpi/pico/Clock.zig
Normal 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
23
hardware/rpi/pico/Led.zig
Normal 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();
|
||||
}
|
||||
36
hardware/rpi/pico/Uart.zig
Normal file
36
hardware/rpi/pico/Uart.zig
Normal 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);
|
||||
}
|
||||
80
hardware/rpi/pico/main.zig
Normal file
80
hardware/rpi/pico/main.zig
Normal 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");
|
||||
}
|
||||
1
hardware/rpi/pico/serial.zig
Normal file
1
hardware/rpi/pico/serial.zig
Normal file
@@ -0,0 +1 @@
|
||||
pub const Usb = @import("serial/Usb.zig");
|
||||
102
hardware/rpi/pico/serial/Usb.zig
Normal file
102
hardware/rpi/pico/serial/Usb.zig
Normal 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];
|
||||
}
|
||||
Reference in New Issue
Block a user