mirror of
https://github.com/mytechnotalent/Embedded-Hacking.git
synced 2026-05-25 16:57:56 +02:00
Fixed Rust drivers
This commit is contained in:
@@ -31,6 +31,9 @@ use rp235x_hal as hal;
|
||||
#[cfg(rp2040)]
|
||||
use rp2040_hal as hal;
|
||||
|
||||
// UART driver for echo demo
|
||||
use crate::uart;
|
||||
|
||||
/// External crystal frequency in Hz (12 MHz).
|
||||
pub(crate) const XTAL_FREQ_HZ: u32 = 12_000_000u32;
|
||||
|
||||
@@ -91,4 +94,33 @@ pub(crate) fn init_pins(
|
||||
hal::gpio::Pins::new(io_bank0, pads_bank0, sio.gpio_bank0, resets)
|
||||
}
|
||||
|
||||
/// Initialise all peripherals and run the UART echo demo.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `pac` - PAC Peripherals singleton (consumed).
|
||||
pub(crate) fn run(mut pac: hal::pac::Peripherals) -> ! {
|
||||
let mut wd = hal::Watchdog::new(pac.WATCHDOG);
|
||||
let clocks = init_clocks(pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS, &mut wd);
|
||||
let pins = init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS);
|
||||
let mut drv = uart::UartDriver::init(pac.UART0, pins.gpio0, pins.gpio1, UART_BAUD, &mut pac.RESETS, &clocks);
|
||||
drv.puts(b"UART driver ready (115200 8N1)\r\n");
|
||||
drv.puts(b"Type characters to echo them back in UPPERCASE:\r\n");
|
||||
echo_loop(&mut drv)
|
||||
}
|
||||
|
||||
/// Run the uppercase echo loop forever.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `drv` - Mutable reference to the UART driver.
|
||||
fn echo_loop(drv: &mut uart::UartDriver) -> ! {
|
||||
loop {
|
||||
if drv.is_readable() {
|
||||
let c = drv.getchar();
|
||||
drv.putchar(uart::UartDriver::to_upper(c));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// End of file
|
||||
|
||||
@@ -76,33 +76,9 @@ pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
|
||||
pub static IMAGE_DEF: hal::block::ImageDef = hal::block::ImageDef::secure_exe();
|
||||
|
||||
/// Application entry point for the UART uppercase echo demo.
|
||||
///
|
||||
/// Initializes UART0 and enters an infinite loop that reads incoming
|
||||
/// characters, converts them to uppercase, and echoes them back.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Does not return.
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let mut pac = hal::pac::Peripherals::take().unwrap();
|
||||
let mut watchdog = hal::Watchdog::new(pac.WATCHDOG);
|
||||
let clocks = board::init_clocks(
|
||||
pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS, &mut watchdog,
|
||||
);
|
||||
let pins = board::init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS);
|
||||
let mut drv = uart::UartDriver::init(
|
||||
pac.UART0, pins.gpio0, pins.gpio1, board::UART_BAUD, &mut pac.RESETS, &clocks,
|
||||
);
|
||||
drv.puts(b"UART driver ready (115200 8N1)\r\n");
|
||||
drv.puts(b"Type characters to echo them back in UPPERCASE:\r\n");
|
||||
loop {
|
||||
if drv.is_readable() {
|
||||
let c = drv.getchar();
|
||||
let upper = uart::UartDriver::to_upper(c);
|
||||
drv.putchar(upper);
|
||||
}
|
||||
}
|
||||
board::run(hal::pac::Peripherals::take().unwrap())
|
||||
}
|
||||
|
||||
// Picotool binary info metadata
|
||||
|
||||
@@ -30,7 +30,7 @@ use fugit::RateExtU32;
|
||||
// Clock trait for accessing system clock frequency
|
||||
use hal::Clock;
|
||||
// GPIO pin types and function selectors
|
||||
use hal::gpio::{FunctionNull, FunctionUart, Pin, PullDown, PullNone};
|
||||
use hal::gpio::{FunctionNull, FunctionSioOutput, FunctionUart, Pin, PullDown, PullNone};
|
||||
// UART configuration and peripheral types
|
||||
use hal::uart::{DataBits, Enabled, StopBits, UartConfig, UartPeripheral};
|
||||
|
||||
@@ -170,4 +170,43 @@ pub(crate) fn init_delay(clocks: &hal::clocks::ClocksManager) -> cortex_m::delay
|
||||
cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz())
|
||||
}
|
||||
|
||||
/// Type alias for the onboard LED pin configured as push-pull output.
|
||||
type LedPin = Pin<hal::gpio::bank0::Gpio25, FunctionSioOutput, PullDown>;
|
||||
|
||||
/// Initialise all peripherals and run the blink demo.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `pac` - PAC Peripherals singleton (consumed).
|
||||
pub(crate) fn run(mut pac: hal::pac::Peripherals) -> ! {
|
||||
let mut wd = hal::Watchdog::new(pac.WATCHDOG);
|
||||
let clocks = init_clocks(pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS, &mut wd);
|
||||
let pins = init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS);
|
||||
let uart = init_uart(pac.UART0, pins.gpio0, pins.gpio1, &mut pac.RESETS, &clocks);
|
||||
let mut delay = init_delay(&clocks);
|
||||
let mut led = crate::blink::BlinkDriver::init(pins.gpio25.into_push_pull_output());
|
||||
uart.write_full_blocking(b"Blink driver initialized on GPIO 25\r\n");
|
||||
blink_loop(&uart, &mut delay, &mut led)
|
||||
}
|
||||
|
||||
/// Toggle LED, report state, and delay in a loop forever.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `uart` - Reference to the enabled UART peripheral for serial output.
|
||||
/// * `delay` - Mutable reference to the blocking delay provider.
|
||||
/// * `led` - Mutable reference to the blink driver.
|
||||
fn blink_loop(
|
||||
uart: &EnabledUart,
|
||||
delay: &mut cortex_m::delay::Delay,
|
||||
led: &mut crate::blink::BlinkDriver<LedPin>,
|
||||
) -> ! {
|
||||
loop {
|
||||
led.toggle();
|
||||
let msg = if led.get_state() { b"LED: ON\r\n" as &[u8] } else { b"LED: OFF\r\n" };
|
||||
uart.write_full_blocking(msg);
|
||||
delay.delay_ms(BLINK_DELAY_MS);
|
||||
}
|
||||
}
|
||||
|
||||
// End of file
|
||||
|
||||
@@ -74,34 +74,9 @@ pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
|
||||
pub static IMAGE_DEF: hal::block::ImageDef = hal::block::ImageDef::secure_exe();
|
||||
|
||||
/// Application entry point for the LED blink demo.
|
||||
///
|
||||
/// Initializes the onboard LED and enters an infinite loop that
|
||||
/// toggles the LED state every BLINK_DELAY_MS milliseconds.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Does not return.
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let mut pac = hal::pac::Peripherals::take().unwrap();
|
||||
let clocks = board::init_clocks(
|
||||
pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS,
|
||||
&mut hal::Watchdog::new(pac.WATCHDOG),
|
||||
);
|
||||
let pins = board::init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS);
|
||||
let uart = board::init_uart(pac.UART0, pins.gpio0, pins.gpio1, &mut pac.RESETS, &clocks);
|
||||
let mut delay = board::init_delay(&clocks);
|
||||
let mut led = blink::BlinkDriver::init(pins.gpio25.into_push_pull_output());
|
||||
uart.write_full_blocking(b"Blink driver initialized on GPIO 25\r\n");
|
||||
loop {
|
||||
led.toggle();
|
||||
if led.get_state() {
|
||||
uart.write_full_blocking(b"LED: ON\r\n");
|
||||
} else {
|
||||
uart.write_full_blocking(b"LED: OFF\r\n");
|
||||
}
|
||||
delay.delay_ms(board::BLINK_DELAY_MS);
|
||||
}
|
||||
board::run(hal::pac::Peripherals::take().unwrap())
|
||||
}
|
||||
|
||||
// Picotool binary info metadata
|
||||
|
||||
@@ -25,12 +25,14 @@
|
||||
//! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
//! SOFTWARE.
|
||||
|
||||
// Interior mutability for shared delay access
|
||||
use core::cell::RefCell;
|
||||
// Rate extension trait for .Hz() baud rate construction
|
||||
use fugit::RateExtU32;
|
||||
// Clock trait for accessing system clock frequency
|
||||
use hal::Clock;
|
||||
// GPIO pin types and function selectors
|
||||
use hal::gpio::{FunctionNull, FunctionUart, Pin, PullDown, PullNone};
|
||||
use hal::gpio::{FunctionNull, FunctionSioInput, FunctionSioOutput, FunctionUart, Pin, PullDown, PullNone, PullUp};
|
||||
// UART configuration and peripheral types
|
||||
use hal::uart::{DataBits, Enabled, StopBits, UartConfig, UartPeripheral};
|
||||
|
||||
@@ -173,4 +175,80 @@ pub(crate) fn init_delay(clocks: &hal::clocks::ClocksManager) -> cortex_m::delay
|
||||
cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz())
|
||||
}
|
||||
|
||||
/// Type alias for the button input pin (GPIO 15, pull-up).
|
||||
type BtnPin = Pin<hal::gpio::bank0::Gpio15, FunctionSioInput, PullUp>;
|
||||
|
||||
/// Type alias for the LED output pin (GPIO 25, push-pull).
|
||||
type LedPin = Pin<hal::gpio::bank0::Gpio25, FunctionSioOutput, PullDown>;
|
||||
|
||||
/// Initialise all peripherals and run the button debounce demo.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `pac` - PAC Peripherals singleton (consumed).
|
||||
pub(crate) fn run(mut pac: hal::pac::Peripherals) -> ! {
|
||||
let mut wd = hal::Watchdog::new(pac.WATCHDOG);
|
||||
let clocks = init_clocks(pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS, &mut wd);
|
||||
let pins = init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS);
|
||||
let uart = init_uart(pac.UART0, pins.gpio0, pins.gpio1, &mut pac.RESETS, &clocks);
|
||||
let delay = RefCell::new(init_delay(&clocks));
|
||||
uart.write_full_blocking(b"Button driver initialized: button=GPIO15 led=GPIO25\r\n");
|
||||
button_demo(&uart, pins.gpio15, pins.gpio25, &delay)
|
||||
}
|
||||
|
||||
/// Create button and LED drivers, then run the polling loop.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `uart` - Reference to the enabled UART peripheral for serial output.
|
||||
/// * `btn_pin` - Default GPIO 15 pin for the button input.
|
||||
/// * `led_pin` - Default GPIO 25 pin for the LED output.
|
||||
/// * `delay` - Shared reference to the delay provider.
|
||||
fn button_demo(
|
||||
uart: &EnabledUart,
|
||||
btn_pin: Pin<hal::gpio::bank0::Gpio15, FunctionNull, PullDown>,
|
||||
led_pin: Pin<hal::gpio::bank0::Gpio25, FunctionNull, PullDown>,
|
||||
delay: &RefCell<cortex_m::delay::Delay>,
|
||||
) -> ! {
|
||||
let mut btn = crate::button::ButtonDriver::init(
|
||||
btn_pin.into_pull_up_input(), DEBOUNCE_MS, |ms| delay.borrow_mut().delay_ms(ms),
|
||||
);
|
||||
let mut led = crate::button::ButtonLed::init(led_pin.into_push_pull_output());
|
||||
let mut last = false;
|
||||
loop { poll_button(uart, &mut btn, &mut led, &mut last, delay); }
|
||||
}
|
||||
|
||||
/// Poll button state, update LED, and report edge transitions.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `uart` - Reference to the enabled UART peripheral for serial output.
|
||||
/// * `btn` - Mutable reference to the button driver.
|
||||
/// * `led` - Mutable reference to the LED driver.
|
||||
/// * `last` - Mutable reference to the previous button state.
|
||||
/// * `delay` - Shared reference to the delay provider.
|
||||
fn poll_button<F: Fn(u32)>(
|
||||
uart: &EnabledUart,
|
||||
btn: &mut crate::button::ButtonDriver<BtnPin, F>,
|
||||
led: &mut crate::button::ButtonLed<LedPin>,
|
||||
last: &mut bool,
|
||||
delay: &RefCell<cortex_m::delay::Delay>,
|
||||
) {
|
||||
let pressed = btn.is_pressed();
|
||||
led.set(pressed);
|
||||
if pressed != *last { report_edge(uart, pressed); *last = pressed; }
|
||||
delay.borrow_mut().delay_ms(POLL_MS);
|
||||
}
|
||||
|
||||
/// Print button press/release message over UART.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `uart` - Reference to the enabled UART peripheral for serial output.
|
||||
/// * `pressed` - `true` if the button is pressed, `false` if released.
|
||||
fn report_edge(uart: &EnabledUart, pressed: bool) {
|
||||
let msg = if pressed { b"Button: PRESSED\r\n" as &[u8] } else { b"Button: RELEASED\r\n" };
|
||||
uart.write_full_blocking(msg);
|
||||
}
|
||||
|
||||
// End of file
|
||||
|
||||
@@ -54,8 +54,6 @@ use panic_halt as _;
|
||||
#[cfg(target_arch = "arm")]
|
||||
use panic_probe as _;
|
||||
|
||||
// Interior mutability for shared peripheral access
|
||||
use core::cell::RefCell;
|
||||
// HAL entry-point macro
|
||||
use hal::entry;
|
||||
|
||||
@@ -78,44 +76,9 @@ pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
|
||||
pub static IMAGE_DEF: hal::block::ImageDef = hal::block::ImageDef::secure_exe();
|
||||
|
||||
/// Application entry point for the button debounce demo.
|
||||
///
|
||||
/// Initializes button and LED, then continuously polls button state
|
||||
/// and mirrors it to the LED with UART reporting on edge transitions.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Does not return.
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let mut pac = hal::pac::Peripherals::take().unwrap();
|
||||
let clocks = board::init_clocks(
|
||||
pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS,
|
||||
&mut hal::Watchdog::new(pac.WATCHDOG),
|
||||
);
|
||||
let pins = board::init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS);
|
||||
let uart = board::init_uart(pac.UART0, pins.gpio0, pins.gpio1, &mut pac.RESETS, &clocks);
|
||||
let delay = RefCell::new(board::init_delay(&clocks));
|
||||
let btn_pin = pins.gpio15.into_pull_up_input();
|
||||
let led_pin = pins.gpio25.into_push_pull_output();
|
||||
let mut btn = button::ButtonDriver::init(btn_pin, board::DEBOUNCE_MS, |ms| {
|
||||
delay.borrow_mut().delay_ms(ms);
|
||||
});
|
||||
let mut led = button::ButtonLed::init(led_pin);
|
||||
uart.write_full_blocking(b"Button driver initialized: button=GPIO15 led=GPIO25\r\n");
|
||||
let mut last_state = false;
|
||||
loop {
|
||||
let pressed = btn.is_pressed();
|
||||
led.set(pressed);
|
||||
if pressed != last_state {
|
||||
if pressed {
|
||||
uart.write_full_blocking(b"Button: PRESSED\r\n");
|
||||
} else {
|
||||
uart.write_full_blocking(b"Button: RELEASED\r\n");
|
||||
}
|
||||
last_state = pressed;
|
||||
}
|
||||
delay.borrow_mut().delay_ms(board::POLL_MS);
|
||||
}
|
||||
board::run(hal::pac::Peripherals::take().unwrap())
|
||||
}
|
||||
|
||||
// Picotool binary info metadata
|
||||
|
||||
@@ -186,28 +186,27 @@ pub(crate) fn init_delay(clocks: &hal::clocks::ClocksManager) -> cortex_m::delay
|
||||
///
|
||||
/// Number of bytes written into the buffer.
|
||||
pub(crate) fn format_duty(buf: &mut [u8], duty: u8) -> usize {
|
||||
let prefix = b"Duty: ";
|
||||
buf[..6].copy_from_slice(prefix);
|
||||
buf[..6].copy_from_slice(b"Duty: ");
|
||||
let mut pos = 6;
|
||||
if duty >= 100 {
|
||||
buf[pos] = b'1'; pos += 1;
|
||||
buf[pos] = b'0'; pos += 1;
|
||||
buf[pos] = b'0'; pos += 1;
|
||||
} else if duty >= 10 {
|
||||
buf[pos] = b' '; pos += 1;
|
||||
buf[pos] = b'0' + duty / 10; pos += 1;
|
||||
buf[pos] = b'0' + duty % 10; pos += 1;
|
||||
} else {
|
||||
buf[pos] = b' '; pos += 1;
|
||||
buf[pos] = b' '; pos += 1;
|
||||
buf[pos] = b'0' + duty; pos += 1;
|
||||
}
|
||||
pos += write_duty_digits(&mut buf[pos..], duty);
|
||||
buf[pos] = b'%'; pos += 1;
|
||||
buf[pos] = b'\r'; pos += 1;
|
||||
buf[pos] = b'\n'; pos += 1;
|
||||
pos
|
||||
}
|
||||
|
||||
/// Write the 3-character right-justified duty digits into `buf`.
|
||||
fn write_duty_digits(buf: &mut [u8], duty: u8) -> usize {
|
||||
if duty >= 100 {
|
||||
buf[0] = b'1'; buf[1] = b'0'; buf[2] = b'0';
|
||||
} else if duty >= 10 {
|
||||
buf[0] = b' '; buf[1] = b'0' + duty / 10; buf[2] = b'0' + duty % 10;
|
||||
} else {
|
||||
buf[0] = b' '; buf[1] = b' '; buf[2] = b'0' + duty;
|
||||
}
|
||||
3
|
||||
}
|
||||
|
||||
/// Sweep the PWM duty cycle from 0% to 100% in steps of 5.
|
||||
///
|
||||
/// # Arguments
|
||||
@@ -224,11 +223,7 @@ pub(crate) fn sweep_up(
|
||||
) {
|
||||
let mut duty: u8 = 0;
|
||||
while duty <= 100 {
|
||||
let level = crate::pwm::duty_to_level(duty, PWM_WRAP) as u16;
|
||||
channel.set_duty_cycle(level).ok();
|
||||
let n = format_duty(buf, duty);
|
||||
uart.write_full_blocking(&buf[..n]);
|
||||
delay.delay_ms(50u32);
|
||||
apply_duty(uart, channel, delay, buf, duty);
|
||||
duty += 5;
|
||||
}
|
||||
}
|
||||
@@ -249,13 +244,99 @@ pub(crate) fn sweep_down(
|
||||
) {
|
||||
let mut duty: i8 = 100;
|
||||
while duty >= 0 {
|
||||
let level = crate::pwm::duty_to_level(duty as u8, PWM_WRAP) as u16;
|
||||
channel.set_duty_cycle(level).ok();
|
||||
let n = format_duty(buf, duty as u8);
|
||||
uart.write_full_blocking(&buf[..n]);
|
||||
delay.delay_ms(50u32);
|
||||
apply_duty(uart, channel, delay, buf, duty as u8);
|
||||
duty -= 5;
|
||||
}
|
||||
}
|
||||
|
||||
/// Apply a single duty step: set PWM level, format, print, and delay.
|
||||
fn apply_duty(
|
||||
uart: &EnabledUart,
|
||||
channel: &mut impl SetDutyCycle,
|
||||
delay: &mut cortex_m::delay::Delay,
|
||||
buf: &mut [u8; 16],
|
||||
duty: u8,
|
||||
) {
|
||||
let level = crate::pwm::duty_to_level(duty, PWM_WRAP) as u16;
|
||||
channel.set_duty_cycle(level).ok();
|
||||
let n = format_duty(buf, duty);
|
||||
uart.write_full_blocking(&buf[..n]);
|
||||
delay.delay_ms(50u32);
|
||||
}
|
||||
|
||||
/// Type alias for PWM slice 4 (onboard LED, GPIO 25).
|
||||
type PwmSlice4 = hal::pwm::Slice<hal::pwm::Pwm4, hal::pwm::FreeRunning>;
|
||||
|
||||
/// Initialise all peripherals and run the PWM breathing demo.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `pac` - PAC Peripherals singleton (consumed).
|
||||
pub(crate) fn run(mut pac: hal::pac::Peripherals) -> ! {
|
||||
let mut wd = hal::Watchdog::new(pac.WATCHDOG);
|
||||
let clocks = init_clocks(pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS, &mut wd);
|
||||
let pins = init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS);
|
||||
let uart = init_uart(pac.UART0, pins.gpio0, pins.gpio1, &mut pac.RESETS, &clocks);
|
||||
let mut delay = init_delay(&clocks);
|
||||
let mut pwm = init_pwm(pac.PWM, &mut pac.RESETS, &clocks, pins.gpio25);
|
||||
uart.write_full_blocking(b"PWM initialized: GPIO25 @ 1000 Hz\r\n");
|
||||
pwm_loop(&uart, &mut pwm, &mut delay)
|
||||
}
|
||||
|
||||
/// Configure PWM slice 4 for 1 kHz output on channel B (GPIO 25).
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `pwm_pac` - PAC PWM peripheral singleton.
|
||||
/// * `resets` - Mutable reference to the RESETS peripheral.
|
||||
/// * `clocks` - Reference to the initialised clock configuration.
|
||||
/// * `led_pin` - Default GPIO 25 pin to bind to PWM channel B.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Configured PWM slice 4 in free-running mode.
|
||||
fn init_pwm(
|
||||
pwm_pac: hal::pac::PWM,
|
||||
resets: &mut hal::pac::RESETS,
|
||||
clocks: &hal::clocks::ClocksManager,
|
||||
led_pin: Pin<hal::gpio::bank0::Gpio25, FunctionNull, PullDown>,
|
||||
) -> PwmSlice4 {
|
||||
let slices = hal::pwm::Slices::new(pwm_pac, resets);
|
||||
let mut slice = slices.pwm4;
|
||||
configure_pwm_div(&mut slice, clocks);
|
||||
slice.set_top(PWM_WRAP as u16);
|
||||
slice.enable();
|
||||
slice.channel_b.output_to(led_pin);
|
||||
slice
|
||||
}
|
||||
|
||||
/// Set the clock divider for a PWM slice based on the system clock.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `slice` - Mutable reference to the PWM slice to configure.
|
||||
/// * `clocks` - Reference to the initialised clock configuration.
|
||||
fn configure_pwm_div(slice: &mut PwmSlice4, clocks: &hal::clocks::ClocksManager) {
|
||||
let sys_hz = clocks.system_clock.freq().to_Hz();
|
||||
let div = crate::pwm::calc_clk_div(sys_hz, PWM_FREQ_HZ, PWM_WRAP);
|
||||
let div_int = div as u8;
|
||||
slice.set_div_int(div_int);
|
||||
slice.set_div_frac((((div - div_int as f32) * 16.0) as u8).min(15));
|
||||
}
|
||||
|
||||
/// Run the PWM duty-cycle sweep loop forever.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `uart` - Reference to the enabled UART peripheral for serial output.
|
||||
/// * `pwm` - Mutable reference to the configured PWM slice.
|
||||
/// * `delay` - Mutable reference to the blocking delay provider.
|
||||
fn pwm_loop(uart: &EnabledUart, pwm: &mut PwmSlice4, delay: &mut cortex_m::delay::Delay) -> ! {
|
||||
let mut buf = [0u8; 16];
|
||||
loop {
|
||||
sweep_up(uart, &mut pwm.channel_b, delay, &mut buf);
|
||||
sweep_down(uart, &mut pwm.channel_b, delay, &mut buf);
|
||||
}
|
||||
}
|
||||
|
||||
// End of file
|
||||
|
||||
@@ -79,40 +79,9 @@ pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
|
||||
pub static IMAGE_DEF: hal::block::ImageDef = hal::block::ImageDef::secure_exe();
|
||||
|
||||
/// Application entry point for the PWM LED breathing demo.
|
||||
///
|
||||
/// Initializes PWM at 1 kHz on the onboard LED and enters an infinite
|
||||
/// loop that sweeps the duty cycle up and down to produce a smooth
|
||||
/// breathing effect, reporting each step over UART.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Does not return.
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let mut pac = hal::pac::Peripherals::take().unwrap();
|
||||
let clocks = board::init_clocks(
|
||||
pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS,
|
||||
&mut hal::Watchdog::new(pac.WATCHDOG),
|
||||
);
|
||||
let pins = board::init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS);
|
||||
let uart = board::init_uart(pac.UART0, pins.gpio0, pins.gpio1, &mut pac.RESETS, &clocks);
|
||||
let mut delay = board::init_delay(&clocks);
|
||||
uart.write_full_blocking(b"PWM initialized: GPIO25 @ 1000 Hz\r\n");
|
||||
let pwm_slices = hal::pwm::Slices::new(pac.PWM, &mut pac.RESETS);
|
||||
let mut pwm_slice = pwm_slices.pwm4;
|
||||
let sys_hz = clocks.system_clock.freq().to_Hz();
|
||||
let div = pwm::calc_clk_div(sys_hz, board::PWM_FREQ_HZ, board::PWM_WRAP);
|
||||
let div_int = div as u8;
|
||||
pwm_slice.set_div_int(div_int);
|
||||
pwm_slice.set_div_frac((((div - div_int as f32) * 16.0) as u8).min(15));
|
||||
pwm_slice.set_top(board::PWM_WRAP as u16);
|
||||
pwm_slice.enable();
|
||||
pwm_slice.channel_b.output_to(pins.gpio25);
|
||||
let mut buf = [0u8; 16];
|
||||
loop {
|
||||
board::sweep_up(&uart, &mut pwm_slice.channel_b, &mut delay, &mut buf);
|
||||
board::sweep_down(&uart, &mut pwm_slice.channel_b, &mut delay, &mut buf);
|
||||
}
|
||||
board::run(hal::pac::Peripherals::take().unwrap())
|
||||
}
|
||||
|
||||
// Picotool binary info metadata
|
||||
|
||||
@@ -186,28 +186,28 @@ pub(crate) fn init_delay(clocks: &hal::clocks::ClocksManager) -> cortex_m::delay
|
||||
///
|
||||
/// Number of bytes written into the buffer.
|
||||
pub(crate) fn format_angle(buf: &mut [u8], angle: i32) -> usize {
|
||||
let prefix = b"Angle: ";
|
||||
buf[..7].copy_from_slice(prefix);
|
||||
buf[..7].copy_from_slice(b"Angle: ");
|
||||
let mut pos = 7;
|
||||
let a = if angle < 0 { 0 } else { angle as u32 };
|
||||
if a >= 100 {
|
||||
buf[pos] = b'0' + (a / 100) as u8; pos += 1;
|
||||
buf[pos] = b'0' + ((a / 10) % 10) as u8; pos += 1;
|
||||
buf[pos] = b'0' + (a % 10) as u8; pos += 1;
|
||||
} else if a >= 10 {
|
||||
buf[pos] = b' '; pos += 1;
|
||||
buf[pos] = b'0' + (a / 10) as u8; pos += 1;
|
||||
buf[pos] = b'0' + (a % 10) as u8; pos += 1;
|
||||
} else {
|
||||
buf[pos] = b' '; pos += 1;
|
||||
buf[pos] = b' '; pos += 1;
|
||||
buf[pos] = b'0' + a as u8; pos += 1;
|
||||
}
|
||||
let suffix = b" deg\r\n";
|
||||
buf[pos..pos + 6].copy_from_slice(suffix);
|
||||
pos += write_angle_digits(&mut buf[pos..], a);
|
||||
buf[pos..pos + 6].copy_from_slice(b" deg\r\n");
|
||||
pos + 6
|
||||
}
|
||||
|
||||
/// Write 3-character right-justified angle digits into `buf`.
|
||||
fn write_angle_digits(buf: &mut [u8], a: u32) -> usize {
|
||||
if a >= 100 {
|
||||
buf[0] = b'0' + (a / 100) as u8;
|
||||
buf[1] = b'0' + ((a / 10) % 10) as u8;
|
||||
buf[2] = b'0' + (a % 10) as u8;
|
||||
} else if a >= 10 {
|
||||
buf[0] = b' '; buf[1] = b'0' + (a / 10) as u8; buf[2] = b'0' + (a % 10) as u8;
|
||||
} else {
|
||||
buf[0] = b' '; buf[1] = b' '; buf[2] = b'0' + a as u8;
|
||||
}
|
||||
3
|
||||
}
|
||||
|
||||
/// Sweep the servo angle upward from 0 to 180 in STEP_DEGREES increments.
|
||||
///
|
||||
/// # Arguments
|
||||
@@ -224,12 +224,7 @@ pub(crate) fn sweep_angle_up(
|
||||
) {
|
||||
let mut angle: i32 = 0;
|
||||
while angle <= 180 {
|
||||
let pulse = crate::servo::angle_to_pulse_us(angle as f32, crate::servo::SERVO_DEFAULT_MIN_US, crate::servo::SERVO_DEFAULT_MAX_US);
|
||||
let level = crate::servo::pulse_us_to_level(pulse as u32, crate::servo::SERVO_WRAP, crate::servo::SERVO_HZ) as u16;
|
||||
channel.set_duty_cycle(level).ok();
|
||||
let n = format_angle(buf, angle);
|
||||
uart.write_full_blocking(&buf[..n]);
|
||||
delay.delay_ms(STEP_DELAY_MS);
|
||||
apply_angle(uart, channel, delay, buf, angle);
|
||||
angle += STEP_DEGREES;
|
||||
}
|
||||
}
|
||||
@@ -250,14 +245,115 @@ pub(crate) fn sweep_angle_down(
|
||||
) {
|
||||
let mut angle: i32 = 180;
|
||||
while angle >= 0 {
|
||||
let pulse = crate::servo::angle_to_pulse_us(angle as f32, crate::servo::SERVO_DEFAULT_MIN_US, crate::servo::SERVO_DEFAULT_MAX_US);
|
||||
let level = crate::servo::pulse_us_to_level(pulse as u32, crate::servo::SERVO_WRAP, crate::servo::SERVO_HZ) as u16;
|
||||
channel.set_duty_cycle(level).ok();
|
||||
let n = format_angle(buf, angle);
|
||||
uart.write_full_blocking(&buf[..n]);
|
||||
delay.delay_ms(STEP_DELAY_MS);
|
||||
apply_angle(uart, channel, delay, buf, angle);
|
||||
angle -= STEP_DEGREES;
|
||||
}
|
||||
}
|
||||
|
||||
/// Apply a single angle step: compute pulse, set PWM, format, print, delay.
|
||||
fn apply_angle(
|
||||
uart: &EnabledUart,
|
||||
channel: &mut impl SetDutyCycle,
|
||||
delay: &mut cortex_m::delay::Delay,
|
||||
buf: &mut [u8; 20],
|
||||
angle: i32,
|
||||
) {
|
||||
let level = compute_servo_level(angle) as u16;
|
||||
channel.set_duty_cycle(level).ok();
|
||||
let n = format_angle(buf, angle);
|
||||
uart.write_full_blocking(&buf[..n]);
|
||||
delay.delay_ms(STEP_DELAY_MS);
|
||||
}
|
||||
|
||||
/// Compute the PWM level for a given angle using servo constants.
|
||||
fn compute_servo_level(angle: i32) -> u32 {
|
||||
let pulse = crate::servo::angle_to_pulse_us(angle as f32, crate::servo::SERVO_DEFAULT_MIN_US, crate::servo::SERVO_DEFAULT_MAX_US);
|
||||
crate::servo::pulse_us_to_level(pulse as u32, crate::servo::SERVO_WRAP, crate::servo::SERVO_HZ)
|
||||
}
|
||||
|
||||
/// Type alias for PWM slice 3 (servo on GPIO 6, channel A).
|
||||
type PwmSlice3 = hal::pwm::Slice<hal::pwm::Pwm3, hal::pwm::FreeRunning>;
|
||||
|
||||
/// Initialise all peripherals and run the servo sweep demo.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `pac` - PAC Peripherals singleton (consumed).
|
||||
pub(crate) fn run(mut pac: hal::pac::Peripherals) -> ! {
|
||||
let mut wd = hal::Watchdog::new(pac.WATCHDOG);
|
||||
let clocks = init_clocks(pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS, &mut wd);
|
||||
let pins = init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS);
|
||||
let uart = init_uart(pac.UART0, pins.gpio0, pins.gpio1, &mut pac.RESETS, &clocks);
|
||||
let mut delay = init_delay(&clocks);
|
||||
let mut pwm = init_servo_pwm(pac.PWM, &mut pac.RESETS, &clocks, pins.gpio6);
|
||||
announce_servo(&uart);
|
||||
servo_loop(&uart, &mut pwm, &mut delay)
|
||||
}
|
||||
|
||||
/// Configure PWM slice 3 for 50 Hz servo output on channel A (GPIO 6).
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `pwm_pac` - PAC PWM peripheral singleton.
|
||||
/// * `resets` - Mutable reference to the RESETS peripheral.
|
||||
/// * `clocks` - Reference to the initialised clock configuration.
|
||||
/// * `servo_pin` - Default GPIO 6 pin to bind to PWM channel A.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Configured PWM slice 3 in free-running mode.
|
||||
fn init_servo_pwm(
|
||||
pwm_pac: hal::pac::PWM,
|
||||
resets: &mut hal::pac::RESETS,
|
||||
clocks: &hal::clocks::ClocksManager,
|
||||
servo_pin: Pin<hal::gpio::bank0::Gpio6, FunctionNull, PullDown>,
|
||||
) -> PwmSlice3 {
|
||||
let slices = hal::pwm::Slices::new(pwm_pac, resets);
|
||||
let mut slice = slices.pwm3;
|
||||
configure_servo_div(&mut slice, clocks);
|
||||
slice.enable();
|
||||
slice.channel_a.output_to(servo_pin);
|
||||
slice
|
||||
}
|
||||
|
||||
/// Set the clock divider and wrap for a servo PWM slice.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `slice` - Mutable reference to the PWM slice to configure.
|
||||
/// * `clocks` - Reference to the initialised clock configuration.
|
||||
fn configure_servo_div(slice: &mut PwmSlice3, clocks: &hal::clocks::ClocksManager) {
|
||||
let sys_hz = clocks.system_clock.freq().to_Hz();
|
||||
let div = crate::servo::calc_clk_div(sys_hz, crate::servo::SERVO_HZ, crate::servo::SERVO_WRAP);
|
||||
let div_int = div as u8;
|
||||
slice.set_div_int(div_int);
|
||||
slice.set_div_frac((((div - div_int as f32) * 16.0) as u8).min(15));
|
||||
slice.set_top(crate::servo::SERVO_WRAP as u16);
|
||||
}
|
||||
|
||||
/// Print the servo initialisation banner over UART.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `uart` - Reference to the enabled UART peripheral for serial output.
|
||||
fn announce_servo(uart: &EnabledUart) {
|
||||
uart.write_full_blocking(b"Servo driver initialized on GPIO 6\r\n");
|
||||
uart.write_full_blocking(b"Sweeping 0 -> 180 -> 0 degrees in 10-degree steps\r\n");
|
||||
}
|
||||
|
||||
/// Run the servo angle sweep loop forever.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `uart` - Reference to the enabled UART peripheral for serial output.
|
||||
/// * `pwm` - Mutable reference to the configured PWM slice.
|
||||
/// * `delay` - Mutable reference to the blocking delay provider.
|
||||
fn servo_loop(uart: &EnabledUart, pwm: &mut PwmSlice3, delay: &mut cortex_m::delay::Delay) -> ! {
|
||||
let mut buf = [0u8; 20];
|
||||
loop {
|
||||
sweep_angle_up(uart, &mut pwm.channel_a, delay, &mut buf);
|
||||
sweep_angle_down(uart, &mut pwm.channel_a, delay, &mut buf);
|
||||
}
|
||||
}
|
||||
|
||||
// End of file
|
||||
|
||||
@@ -78,40 +78,9 @@ pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
|
||||
pub static IMAGE_DEF: hal::block::ImageDef = hal::block::ImageDef::secure_exe();
|
||||
|
||||
/// Application entry point for the servo sweep demo.
|
||||
///
|
||||
/// Initializes the servo on GPIO 6 and continuously sweeps 0-180-0
|
||||
/// degrees in 10-degree increments, reporting each angle over UART.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Does not return.
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let mut pac = hal::pac::Peripherals::take().unwrap();
|
||||
let clocks = board::init_clocks(
|
||||
pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS,
|
||||
&mut hal::Watchdog::new(pac.WATCHDOG),
|
||||
);
|
||||
let pins = board::init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS);
|
||||
let uart = board::init_uart(pac.UART0, pins.gpio0, pins.gpio1, &mut pac.RESETS, &clocks);
|
||||
let mut delay = board::init_delay(&clocks);
|
||||
let pwm_slices = hal::pwm::Slices::new(pac.PWM, &mut pac.RESETS);
|
||||
let mut pwm = pwm_slices.pwm3;
|
||||
let sys_hz = clocks.system_clock.freq().to_Hz();
|
||||
let div = servo::calc_clk_div(sys_hz, servo::SERVO_HZ, servo::SERVO_WRAP);
|
||||
let div_int = div as u8;
|
||||
pwm.set_div_int(div_int);
|
||||
pwm.set_div_frac((((div - div_int as f32) * 16.0) as u8).min(15));
|
||||
pwm.set_top(servo::SERVO_WRAP as u16);
|
||||
pwm.enable();
|
||||
pwm.channel_a.output_to(pins.gpio6);
|
||||
uart.write_full_blocking(b"Servo driver initialized on GPIO 6\r\n");
|
||||
uart.write_full_blocking(b"Sweeping 0 -> 180 -> 0 degrees in 10-degree steps\r\n");
|
||||
let mut buf = [0u8; 20];
|
||||
loop {
|
||||
board::sweep_angle_up(&uart, &mut pwm.channel_a, &mut delay, &mut buf);
|
||||
board::sweep_angle_down(&uart, &mut pwm.channel_a, &mut delay, &mut buf);
|
||||
}
|
||||
board::run(hal::pac::Peripherals::take().unwrap())
|
||||
}
|
||||
|
||||
// Picotool binary info metadata
|
||||
|
||||
@@ -183,37 +183,133 @@ pub(crate) fn init_delay(clocks: &hal::clocks::ClocksManager) -> cortex_m::delay
|
||||
///
|
||||
/// Number of bytes written into the buffer.
|
||||
pub(crate) fn format_adc_line(buf: &mut [u8], mv: u32, temp_int: i32, temp_frac: u8) -> usize {
|
||||
let prefix = b"ADC0: ";
|
||||
buf[..6].copy_from_slice(prefix);
|
||||
buf[..6].copy_from_slice(b"ADC0: ");
|
||||
let mut pos = 6;
|
||||
let thousands = ((mv / 1000) % 10) as u8;
|
||||
let hundreds = ((mv / 100) % 10) as u8;
|
||||
let tens = ((mv / 10) % 10) as u8;
|
||||
let ones = (mv % 10) as u8;
|
||||
buf[pos] = b'0' + thousands; pos += 1;
|
||||
buf[pos] = b'0' + hundreds; pos += 1;
|
||||
buf[pos] = b'0' + tens; pos += 1;
|
||||
buf[pos] = b'0' + ones; pos += 1;
|
||||
let mid = b" mV | Chip temp: ";
|
||||
buf[pos..pos + 19].copy_from_slice(mid);
|
||||
pos += write_mv_digits(&mut buf[pos..], mv);
|
||||
buf[pos..pos + 19].copy_from_slice(b" mV | Chip temp: ");
|
||||
pos += 19;
|
||||
let abs_temp = if temp_int < 0 { -temp_int } else { temp_int } as u32;
|
||||
if temp_int < 0 {
|
||||
buf[pos] = b'-'; pos += 1;
|
||||
}
|
||||
if abs_temp >= 100 {
|
||||
buf[pos] = b'0' + ((abs_temp / 100) % 10) as u8; pos += 1;
|
||||
}
|
||||
if abs_temp >= 10 {
|
||||
buf[pos] = b'0' + ((abs_temp / 10) % 10) as u8; pos += 1;
|
||||
}
|
||||
buf[pos] = b'0' + (abs_temp % 10) as u8; pos += 1;
|
||||
pos += write_temp(&mut buf[pos..], temp_int, temp_frac);
|
||||
buf[pos..pos + 4].copy_from_slice(b" C\r\n");
|
||||
pos + 4
|
||||
}
|
||||
|
||||
/// Write 4-digit millivolt value into `buf`.
|
||||
fn write_mv_digits(buf: &mut [u8], mv: u32) -> usize {
|
||||
buf[0] = b'0' + ((mv / 1000) % 10) as u8;
|
||||
buf[1] = b'0' + ((mv / 100) % 10) as u8;
|
||||
buf[2] = b'0' + ((mv / 10) % 10) as u8;
|
||||
buf[3] = b'0' + (mv % 10) as u8;
|
||||
4
|
||||
}
|
||||
|
||||
/// Write temperature as "[-]NN.F" into `buf`.
|
||||
fn write_temp(buf: &mut [u8], temp_int: i32, temp_frac: u8) -> usize {
|
||||
let mut pos = 0;
|
||||
let abs_temp = if temp_int < 0 { buf[pos] = b'-'; pos += 1; -temp_int } else { temp_int } as u32;
|
||||
pos += write_min_digits(&mut buf[pos..], abs_temp);
|
||||
buf[pos] = b'.'; pos += 1;
|
||||
buf[pos] = b'0' + temp_frac; pos += 1;
|
||||
let suffix = b" C\r\n";
|
||||
buf[pos..pos + 4].copy_from_slice(suffix);
|
||||
pos += 4;
|
||||
pos
|
||||
}
|
||||
|
||||
/// Write a u32 with minimum digits (no leading zeros).
|
||||
fn write_min_digits(buf: &mut [u8], val: u32) -> usize {
|
||||
let mut pos = 0;
|
||||
if val >= 100 { buf[pos] = b'0' + ((val / 100) % 10) as u8; pos += 1; }
|
||||
if val >= 10 { buf[pos] = b'0' + ((val / 10) % 10) as u8; pos += 1; }
|
||||
buf[pos] = b'0' + (val % 10) as u8;
|
||||
pos + 1
|
||||
}
|
||||
|
||||
/// Type alias for the ADC input pin on GPIO 26.
|
||||
type Gpio26Adc = hal::adc::AdcPin<Pin<hal::gpio::bank0::Gpio26, FunctionNull, PullDown>>;
|
||||
|
||||
/// Initialise all peripherals and run the ADC demo.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `pac` - PAC Peripherals singleton (consumed).
|
||||
pub(crate) fn run(mut pac: hal::pac::Peripherals) -> ! {
|
||||
let mut wd = hal::Watchdog::new(pac.WATCHDOG);
|
||||
let clocks = init_clocks(pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS, &mut wd);
|
||||
let pins = init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS);
|
||||
let uart = init_uart(pac.UART0, pins.gpio0, pins.gpio1, &mut pac.RESETS, &clocks);
|
||||
let mut delay = init_delay(&clocks);
|
||||
let (mut adc, mut adc_pin, mut temp) = init_adc(pac.ADC, pins.gpio26, &mut pac.RESETS);
|
||||
uart.write_full_blocking(b"ADC driver initialized: GPIO26 (channel 0)\r\n");
|
||||
adc_loop(&uart, &mut adc, &mut adc_pin, &mut temp, &mut delay)
|
||||
}
|
||||
|
||||
/// Create the ADC peripheral, GPIO 26 input channel, and temperature sensor.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `adc_pac` - PAC ADC peripheral singleton.
|
||||
/// * `gpio26` - Default GPIO 26 pin to use as ADC input.
|
||||
/// * `resets` - Mutable reference to the RESETS peripheral.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Tuple of (ADC driver, ADC pin channel, temperature sensor channel).
|
||||
fn init_adc(
|
||||
adc_pac: hal::pac::ADC,
|
||||
gpio26: Pin<hal::gpio::bank0::Gpio26, FunctionNull, PullDown>,
|
||||
resets: &mut hal::pac::RESETS,
|
||||
) -> (hal::Adc, Gpio26Adc, hal::adc::TempSense) {
|
||||
let mut adc = hal::Adc::new(adc_pac, resets);
|
||||
let pin = hal::adc::AdcPin::new(gpio26).unwrap();
|
||||
let temp = adc.take_temp_sensor().unwrap();
|
||||
(adc, pin, temp)
|
||||
}
|
||||
|
||||
/// Sample voltage and temperature, format, and print in a loop.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `uart` - Reference to the enabled UART peripheral for serial output.
|
||||
/// * `adc` - Mutable reference to the ADC driver.
|
||||
/// * `adc_pin` - Mutable reference to the GPIO 26 ADC channel.
|
||||
/// * `temp` - Mutable reference to the temperature sensor channel.
|
||||
/// * `delay` - Mutable reference to the blocking delay provider.
|
||||
fn adc_loop(
|
||||
uart: &EnabledUart,
|
||||
adc: &mut hal::Adc,
|
||||
adc_pin: &mut Gpio26Adc,
|
||||
temp: &mut hal::adc::TempSense,
|
||||
delay: &mut cortex_m::delay::Delay,
|
||||
) -> ! {
|
||||
let mut buf = [0u8; 48];
|
||||
loop {
|
||||
let (mv, temp_int, temp_frac) = read_adc(adc, adc_pin, temp);
|
||||
let n = format_adc_line(&mut buf, mv, temp_int, temp_frac);
|
||||
uart.write_full_blocking(&buf[..n]);
|
||||
delay.delay_ms(POLL_MS);
|
||||
}
|
||||
}
|
||||
|
||||
/// Read voltage and temperature from the ADC.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `adc` - Mutable reference to the ADC driver.
|
||||
/// * `adc_pin` - Mutable reference to the GPIO 26 ADC channel.
|
||||
/// * `temp` - Mutable reference to the temperature sensor channel.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Tuple of (millivolts, integer temperature, fractional temperature digit).
|
||||
fn read_adc(
|
||||
adc: &mut hal::Adc,
|
||||
adc_pin: &mut Gpio26Adc,
|
||||
temp: &mut hal::adc::TempSense,
|
||||
) -> (u32, i32, u8) {
|
||||
let raw_v: u16 = adc.read(adc_pin).unwrap();
|
||||
let mv = crate::adc::raw_to_mv(raw_v);
|
||||
let raw_t: u16 = adc.read(temp).unwrap();
|
||||
let celsius = crate::adc::raw_to_celsius(raw_t);
|
||||
let temp_int = celsius as i32;
|
||||
let temp_frac = (((celsius - temp_int as f32) * 10.0) as u8).min(9);
|
||||
(mv, temp_int, temp_frac)
|
||||
}
|
||||
|
||||
// End of file
|
||||
|
||||
@@ -78,39 +78,9 @@ pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
|
||||
pub static IMAGE_DEF: hal::block::ImageDef = hal::block::ImageDef::secure_exe();
|
||||
|
||||
/// Application entry point for the ADC voltage and temperature demo.
|
||||
///
|
||||
/// Initializes the ADC on GPIO26 channel 0 and prints readings
|
||||
/// every 500 ms over UART.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Does not return.
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let mut pac = hal::pac::Peripherals::take().unwrap();
|
||||
let clocks = board::init_clocks(
|
||||
pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS,
|
||||
&mut hal::Watchdog::new(pac.WATCHDOG),
|
||||
);
|
||||
let pins = board::init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS);
|
||||
let uart = board::init_uart(pac.UART0, pins.gpio0, pins.gpio1, &mut pac.RESETS, &clocks);
|
||||
let mut delay = board::init_delay(&clocks);
|
||||
let mut adc_hw = hal::Adc::new(pac.ADC, &mut pac.RESETS);
|
||||
let mut adc_pin = hal::adc::AdcPin::new(pins.gpio26).unwrap();
|
||||
let mut temp_sensor = adc_hw.take_temp_sensor().unwrap();
|
||||
uart.write_full_blocking(b"ADC driver initialized: GPIO26 (channel 0)\r\n");
|
||||
let mut buf = [0u8; 48];
|
||||
loop {
|
||||
let raw_v: u16 = adc_hw.read(&mut adc_pin).unwrap();
|
||||
let mv = adc::raw_to_mv(raw_v);
|
||||
let raw_t: u16 = adc_hw.read(&mut temp_sensor).unwrap();
|
||||
let temp = adc::raw_to_celsius(raw_t);
|
||||
let temp_int = temp as i32;
|
||||
let temp_frac = (((temp - temp_int as f32) * 10.0) as u8).min(9);
|
||||
let n = board::format_adc_line(&mut buf, mv, temp_int, temp_frac);
|
||||
uart.write_full_blocking(&buf[..n]);
|
||||
delay.delay_ms(board::POLL_MS);
|
||||
}
|
||||
board::run(hal::pac::Peripherals::take().unwrap())
|
||||
}
|
||||
|
||||
// Picotool binary info metadata
|
||||
|
||||
@@ -32,7 +32,7 @@ use fugit::RateExtU32;
|
||||
// Clock trait for accessing system clock frequency
|
||||
use hal::Clock;
|
||||
// GPIO pin types and function selectors
|
||||
use hal::gpio::{FunctionNull, FunctionUart, Pin, PullDown, PullNone};
|
||||
use hal::gpio::{FunctionI2C, FunctionNull, FunctionUart, Pin, PullDown, PullNone, PullUp};
|
||||
// UART configuration and peripheral types
|
||||
use hal::uart::{DataBits, Enabled, StopBits, UartConfig, UartPeripheral};
|
||||
|
||||
@@ -190,4 +190,77 @@ pub(crate) fn probe_addr(i2c: &mut impl I2c, addr: u8) -> bool {
|
||||
i2c.read(addr, &mut dummy).is_ok()
|
||||
}
|
||||
|
||||
/// Initialise all peripherals and run the I2C bus scanner demo.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `pac` - PAC Peripherals singleton (consumed).
|
||||
pub(crate) fn run(mut pac: hal::pac::Peripherals) -> ! {
|
||||
let mut wd = hal::Watchdog::new(pac.WATCHDOG);
|
||||
let clocks = init_clocks(pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS, &mut wd);
|
||||
let pins = init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS);
|
||||
let uart = init_uart(pac.UART0, pins.gpio0, pins.gpio1, &mut pac.RESETS, &clocks);
|
||||
let mut delay = init_delay(&clocks);
|
||||
let mut i2c = init_i2c(pac.I2C1, pins.gpio2, pins.gpio3, &mut pac.RESETS, &clocks);
|
||||
uart.write_full_blocking(b"I2C driver initialized: I2C1 @ 100000 Hz SDA=GPIO2 SCL=GPIO3\r\n");
|
||||
scan_loop(&uart, &mut i2c, &mut delay)
|
||||
}
|
||||
|
||||
/// Initialise I2C1 on SDA=GPIO2 / SCL=GPIO3.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `i2c1` - PAC I2C1 peripheral singleton.
|
||||
/// * `sda` - Default GPIO 2 pin (will be reconfigured for I2C).
|
||||
/// * `scl` - Default GPIO 3 pin (will be reconfigured for I2C).
|
||||
/// * `resets` - Mutable reference to the RESETS peripheral.
|
||||
/// * `clocks` - Reference to the initialised clock configuration.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Configured I2C1 bus controller.
|
||||
fn init_i2c(
|
||||
i2c1: hal::pac::I2C1,
|
||||
sda: Pin<hal::gpio::bank0::Gpio2, FunctionNull, PullDown>,
|
||||
scl: Pin<hal::gpio::bank0::Gpio3, FunctionNull, PullDown>,
|
||||
resets: &mut hal::pac::RESETS,
|
||||
clocks: &hal::clocks::ClocksManager,
|
||||
) -> impl I2c {
|
||||
let sda = sda.reconfigure::<FunctionI2C, PullUp>();
|
||||
let scl = scl.reconfigure::<FunctionI2C, PullUp>();
|
||||
hal::I2C::i2c1(i2c1, sda, scl, I2C_BAUD.Hz(), resets, clocks.system_clock.freq())
|
||||
}
|
||||
|
||||
/// Run the I2C address scan loop forever.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `uart` - Reference to the enabled UART peripheral for serial output.
|
||||
/// * `i2c` - Mutable reference to the I2C bus controller.
|
||||
/// * `delay` - Mutable reference to the blocking delay provider.
|
||||
fn scan_loop(uart: &EnabledUart, i2c: &mut impl I2c, delay: &mut cortex_m::delay::Delay) -> ! {
|
||||
let mut buf = [0u8; 80];
|
||||
loop {
|
||||
let n = crate::i2c::format_scan_header(&mut buf);
|
||||
uart.write_full_blocking(&buf[..n]);
|
||||
scan_addresses(uart, i2c, &mut buf);
|
||||
delay.delay_ms(SCAN_DELAY_MS);
|
||||
}
|
||||
}
|
||||
|
||||
/// Scan all 128 addresses and print the formatted result.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `uart` - Reference to the enabled UART peripheral for serial output.
|
||||
/// * `i2c` - Mutable reference to the I2C bus controller.
|
||||
/// * `buf` - Scratch buffer for formatting output.
|
||||
fn scan_addresses(uart: &EnabledUart, i2c: &mut impl I2c, buf: &mut [u8; 80]) {
|
||||
for addr in 0u8..128 {
|
||||
let found = !crate::i2c::is_reserved(addr) && probe_addr(i2c, addr);
|
||||
let n = crate::i2c::format_scan_entry(buf, addr, found);
|
||||
uart.write_full_blocking(&buf[..n]);
|
||||
}
|
||||
}
|
||||
|
||||
// End of file
|
||||
|
||||
@@ -87,33 +87,36 @@ pub fn format_scan_header(buf: &mut [u8]) -> usize {
|
||||
///
|
||||
/// Number of bytes written into the buffer.
|
||||
pub fn format_scan_entry(buf: &mut [u8], addr: u8, found: bool) -> usize {
|
||||
let mut pos = 0;
|
||||
if addr % 16 == 0 {
|
||||
buf[pos] = hex_digit((addr >> 4) & 0x0F); pos += 1;
|
||||
buf[pos] = hex_digit(addr & 0x0F); pos += 1;
|
||||
buf[pos] = b':'; pos += 1;
|
||||
buf[pos] = b' '; pos += 1;
|
||||
}
|
||||
if is_reserved(addr) {
|
||||
buf[pos] = b' '; pos += 1;
|
||||
buf[pos] = b' '; pos += 1;
|
||||
buf[pos] = b' '; pos += 1;
|
||||
} else if found {
|
||||
buf[pos] = hex_digit((addr >> 4) & 0x0F); pos += 1;
|
||||
buf[pos] = hex_digit(addr & 0x0F); pos += 1;
|
||||
buf[pos] = b' '; pos += 1;
|
||||
} else {
|
||||
buf[pos] = b'-'; pos += 1;
|
||||
buf[pos] = b'-'; pos += 1;
|
||||
buf[pos] = b' '; pos += 1;
|
||||
}
|
||||
if addr % 16 == 15 {
|
||||
buf[pos] = b'\r'; pos += 1;
|
||||
buf[pos] = b'\n'; pos += 1;
|
||||
}
|
||||
let mut pos = format_row_prefix(buf, addr);
|
||||
pos += format_cell(&mut buf[pos..], addr, found);
|
||||
if addr % 16 == 15 { buf[pos] = b'\r'; pos += 1; buf[pos] = b'\n'; pos += 1; }
|
||||
pos
|
||||
}
|
||||
|
||||
/// Write the row prefix ("XX: ") if addr is at a 16-byte boundary.
|
||||
fn format_row_prefix(buf: &mut [u8], addr: u8) -> usize {
|
||||
if addr % 16 != 0 { return 0; }
|
||||
buf[0] = hex_digit((addr >> 4) & 0x0F);
|
||||
buf[1] = hex_digit(addr & 0x0F);
|
||||
buf[2] = b':';
|
||||
buf[3] = b' ';
|
||||
4
|
||||
}
|
||||
|
||||
/// Write a single cell: "XX " if found, "-- " if not, " " if reserved.
|
||||
fn format_cell(buf: &mut [u8], addr: u8, found: bool) -> usize {
|
||||
let cell = cell_bytes(addr, found);
|
||||
buf[..3].copy_from_slice(&cell);
|
||||
3
|
||||
}
|
||||
|
||||
/// Return the 3-byte cell content for an I2C scan address.
|
||||
fn cell_bytes(addr: u8, found: bool) -> [u8; 3] {
|
||||
if is_reserved(addr) { return [b' ', b' ', b' ']; }
|
||||
if found { [hex_digit((addr >> 4) & 0x0F), hex_digit(addr & 0x0F), b' '] }
|
||||
else { [b'-', b'-', b' '] }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
// Import all parent module items
|
||||
|
||||
@@ -56,14 +56,8 @@ use panic_halt as _;
|
||||
#[cfg(target_arch = "arm")]
|
||||
use panic_probe as _;
|
||||
|
||||
// Rate extension trait for .Hz() baud rate construction
|
||||
use fugit::RateExtU32;
|
||||
// Clock trait for accessing system clock frequency
|
||||
use hal::Clock;
|
||||
// HAL entry-point macro
|
||||
use hal::entry;
|
||||
// GPIO traits for I2C pin reconfiguration
|
||||
use hal::gpio::{FunctionI2C, PullUp};
|
||||
|
||||
// Alias our HAL crate
|
||||
#[cfg(rp2350)]
|
||||
@@ -84,42 +78,9 @@ pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
|
||||
pub static IMAGE_DEF: hal::block::ImageDef = hal::block::ImageDef::secure_exe();
|
||||
|
||||
/// Application entry point for the I2C bus scanner demo.
|
||||
///
|
||||
/// Initializes I2C1 at 100 kHz on SDA=GPIO2 / SCL=GPIO3 and prints
|
||||
/// a formatted hex table of all responding device addresses over UART,
|
||||
/// repeating every 5 seconds.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Does not return.
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let mut pac = hal::pac::Peripherals::take().unwrap();
|
||||
let clocks = board::init_clocks(
|
||||
pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS,
|
||||
&mut hal::Watchdog::new(pac.WATCHDOG),
|
||||
);
|
||||
let pins = board::init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS);
|
||||
let uart = board::init_uart(pac.UART0, pins.gpio0, pins.gpio1, &mut pac.RESETS, &clocks);
|
||||
let mut delay = board::init_delay(&clocks);
|
||||
let sda_pin = pins.gpio2.reconfigure::<FunctionI2C, PullUp>();
|
||||
let scl_pin = pins.gpio3.reconfigure::<FunctionI2C, PullUp>();
|
||||
let mut i2c = hal::I2C::i2c1(
|
||||
pac.I2C1, sda_pin, scl_pin, board::I2C_BAUD.Hz(),
|
||||
&mut pac.RESETS, clocks.system_clock.freq(),
|
||||
);
|
||||
uart.write_full_blocking(b"I2C driver initialized: I2C1 @ 100000 Hz SDA=GPIO2 SCL=GPIO3\r\n");
|
||||
let mut buf = [0u8; 80];
|
||||
loop {
|
||||
let n = i2c::format_scan_header(&mut buf);
|
||||
uart.write_full_blocking(&buf[..n]);
|
||||
for addr in 0u8..128 {
|
||||
let found = !i2c::is_reserved(addr) && board::probe_addr(&mut i2c, addr);
|
||||
let n = i2c::format_scan_entry(&mut buf, addr, found);
|
||||
uart.write_full_blocking(&buf[..n]);
|
||||
}
|
||||
delay.delay_ms(board::SCAN_DELAY_MS);
|
||||
}
|
||||
board::run(hal::pac::Peripherals::take().unwrap())
|
||||
}
|
||||
|
||||
// Picotool binary info metadata
|
||||
|
||||
@@ -32,7 +32,7 @@ use fugit::RateExtU32;
|
||||
// Clock trait for accessing system clock frequency
|
||||
use hal::Clock;
|
||||
// GPIO pin types and function selectors
|
||||
use hal::gpio::{FunctionNull, FunctionUart, Pin, PullDown, PullNone};
|
||||
use hal::gpio::{FunctionI2C, FunctionNull, FunctionUart, Pin, PullDown, PullNone, PullUp};
|
||||
// UART configuration and peripheral types
|
||||
use hal::uart::{DataBits, Enabled, StopBits, UartConfig, UartPeripheral};
|
||||
|
||||
@@ -246,14 +246,19 @@ fn lcd_send(i2c: &mut impl I2c, addr: u8, value: u8, mode: u8, delay: &mut corte
|
||||
/// * `addr` - 7-bit I2C address of the PCF8574.
|
||||
/// * `delay` - Delay provider for timing.
|
||||
fn lcd_hd44780_reset(i2c: &mut impl I2c, addr: u8, delay: &mut cortex_m::delay::Delay) {
|
||||
lcd_reset_pulse_3x(i2c, addr, delay);
|
||||
lcd_write4(i2c, addr, 0x02, 0, delay);
|
||||
delay.delay_us(150);
|
||||
}
|
||||
|
||||
/// Send three 0x03 nibbles with required power-on delays.
|
||||
fn lcd_reset_pulse_3x(i2c: &mut impl I2c, addr: u8, delay: &mut cortex_m::delay::Delay) {
|
||||
lcd_write4(i2c, addr, 0x03, 0, delay);
|
||||
delay.delay_ms(5);
|
||||
lcd_write4(i2c, addr, 0x03, 0, delay);
|
||||
delay.delay_us(150);
|
||||
lcd_write4(i2c, addr, 0x03, 0, delay);
|
||||
delay.delay_us(150);
|
||||
lcd_write4(i2c, addr, 0x02, 0, delay);
|
||||
delay.delay_us(150);
|
||||
}
|
||||
|
||||
/// Send post-reset configuration commands to the HD44780.
|
||||
@@ -312,9 +317,14 @@ pub(crate) fn setup_display(
|
||||
) {
|
||||
lcd_hd44780_reset(i2c, LCD_I2C_ADDR, delay);
|
||||
lcd_hd44780_configure(i2c, LCD_I2C_ADDR, delay);
|
||||
lcd_show_title(i2c, delay);
|
||||
uart.write_full_blocking(b"LCD 1602 driver initialized at I2C addr 0x27\r\n");
|
||||
}
|
||||
|
||||
/// Write the title text on LCD row 0.
|
||||
fn lcd_show_title(i2c: &mut impl I2c, delay: &mut cortex_m::delay::Delay) {
|
||||
lcd_set_cursor(i2c, LCD_I2C_ADDR, 0, 0, delay);
|
||||
lcd_puts(i2c, LCD_I2C_ADDR, b"Reverse Eng.", delay);
|
||||
uart.write_full_blocking(b"LCD 1602 driver initialized at I2C addr 0x27\r\n");
|
||||
}
|
||||
|
||||
/// Format and display the next counter value on LCD line 1.
|
||||
@@ -334,11 +344,78 @@ pub(crate) fn update_counter(
|
||||
let mut buf = [0u8; 16];
|
||||
let n = crate::lcd1602::format_counter(&mut buf, *count);
|
||||
*count += 1;
|
||||
lcd_set_cursor(i2c, LCD_I2C_ADDR, 1, 0, delay);
|
||||
lcd_puts(i2c, LCD_I2C_ADDR, &buf[..n], delay);
|
||||
uart.write_full_blocking(&buf[..n]);
|
||||
uart.write_full_blocking(b"\r\n");
|
||||
lcd_display_counter(i2c, delay, &buf[..n]);
|
||||
uart_log_counter(uart, &buf[..n]);
|
||||
delay.delay_ms(COUNTER_DELAY_MS);
|
||||
}
|
||||
|
||||
/// Write counter text to LCD line 1.
|
||||
fn lcd_display_counter(i2c: &mut impl I2c, delay: &mut cortex_m::delay::Delay, text: &[u8]) {
|
||||
lcd_set_cursor(i2c, LCD_I2C_ADDR, 1, 0, delay);
|
||||
lcd_puts(i2c, LCD_I2C_ADDR, text, delay);
|
||||
}
|
||||
|
||||
/// Log counter text over UART with trailing CRLF.
|
||||
fn uart_log_counter(uart: &EnabledUart, text: &[u8]) {
|
||||
uart.write_full_blocking(text);
|
||||
uart.write_full_blocking(b"\r\n");
|
||||
}
|
||||
|
||||
/// Initialise all peripherals and run the LCD 1602 counter demo.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `pac` - PAC Peripherals singleton (consumed).
|
||||
pub(crate) fn run(mut pac: hal::pac::Peripherals) -> ! {
|
||||
let mut wd = hal::Watchdog::new(pac.WATCHDOG);
|
||||
let clocks = init_clocks(pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS, &mut wd);
|
||||
let pins = init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS);
|
||||
let uart = init_uart(pac.UART0, pins.gpio0, pins.gpio1, &mut pac.RESETS, &clocks);
|
||||
let mut delay = init_delay(&clocks);
|
||||
let mut i2c = init_i2c(pac.I2C1, pins.gpio2, pins.gpio3, &mut pac.RESETS, &clocks);
|
||||
setup_display(&mut i2c, &uart, &mut delay);
|
||||
counter_loop(&mut i2c, &uart, &mut delay)
|
||||
}
|
||||
|
||||
/// Initialise I2C1 on SDA=GPIO2 / SCL=GPIO3.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `i2c1` - PAC I2C1 peripheral singleton.
|
||||
/// * `sda` - Default GPIO 2 pin (will be reconfigured for I2C).
|
||||
/// * `scl` - Default GPIO 3 pin (will be reconfigured for I2C).
|
||||
/// * `resets` - Mutable reference to the RESETS peripheral.
|
||||
/// * `clocks` - Reference to the initialised clock configuration.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Configured I2C1 bus controller.
|
||||
fn init_i2c(
|
||||
i2c1: hal::pac::I2C1,
|
||||
sda: Pin<hal::gpio::bank0::Gpio2, FunctionNull, PullDown>,
|
||||
scl: Pin<hal::gpio::bank0::Gpio3, FunctionNull, PullDown>,
|
||||
resets: &mut hal::pac::RESETS,
|
||||
clocks: &hal::clocks::ClocksManager,
|
||||
) -> impl I2c {
|
||||
let sda = sda.reconfigure::<FunctionI2C, PullUp>();
|
||||
let scl = scl.reconfigure::<FunctionI2C, PullUp>();
|
||||
hal::I2C::i2c1(i2c1, sda, scl, I2C_BAUD.Hz(), resets, clocks.system_clock.freq())
|
||||
}
|
||||
|
||||
/// Run the counter display loop forever.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `i2c` - Mutable reference to the I2C bus controller.
|
||||
/// * `uart` - Reference to the enabled UART peripheral for serial output.
|
||||
/// * `delay` - Mutable reference to the blocking delay provider.
|
||||
fn counter_loop(
|
||||
i2c: &mut impl I2c,
|
||||
uart: &EnabledUart,
|
||||
delay: &mut cortex_m::delay::Delay,
|
||||
) -> ! {
|
||||
let mut count: u32 = 0;
|
||||
loop { update_counter(i2c, uart, delay, &mut count); }
|
||||
}
|
||||
|
||||
// End of file
|
||||
|
||||
@@ -56,14 +56,8 @@ use panic_halt as _;
|
||||
#[cfg(target_arch = "arm")]
|
||||
use panic_probe as _;
|
||||
|
||||
// Rate extension trait for .Hz() baud rate construction
|
||||
use fugit::RateExtU32;
|
||||
// Clock trait for accessing system clock frequency
|
||||
use hal::Clock;
|
||||
// HAL entry-point macro
|
||||
use hal::entry;
|
||||
// GPIO traits for I2C pin reconfiguration
|
||||
use hal::gpio::{FunctionI2C, PullUp};
|
||||
|
||||
// Alias our HAL crate
|
||||
#[cfg(rp2350)]
|
||||
@@ -84,34 +78,9 @@ pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
|
||||
pub static IMAGE_DEF: hal::block::ImageDef = hal::block::ImageDef::secure_exe();
|
||||
|
||||
/// Application entry point for the LCD 1602 counter demo.
|
||||
///
|
||||
/// Initializes the LCD over I2C with a static title on line 0 and
|
||||
/// continuously increments a counter on line 1 every second.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Does not return.
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let mut pac = hal::pac::Peripherals::take().unwrap();
|
||||
let clocks = board::init_clocks(
|
||||
pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS,
|
||||
&mut hal::Watchdog::new(pac.WATCHDOG),
|
||||
);
|
||||
let pins = board::init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS);
|
||||
let uart = board::init_uart(pac.UART0, pins.gpio0, pins.gpio1, &mut pac.RESETS, &clocks);
|
||||
let mut delay = board::init_delay(&clocks);
|
||||
let sda_pin = pins.gpio2.reconfigure::<FunctionI2C, PullUp>();
|
||||
let scl_pin = pins.gpio3.reconfigure::<FunctionI2C, PullUp>();
|
||||
let mut i2c = hal::I2C::i2c1(
|
||||
pac.I2C1, sda_pin, scl_pin, board::I2C_BAUD.Hz(),
|
||||
&mut pac.RESETS, clocks.system_clock.freq(),
|
||||
);
|
||||
board::setup_display(&mut i2c, &uart, &mut delay);
|
||||
let mut count: u32 = 0;
|
||||
loop {
|
||||
board::update_counter(&mut i2c, &uart, &mut delay, &mut count);
|
||||
}
|
||||
board::run(hal::pac::Peripherals::take().unwrap())
|
||||
}
|
||||
|
||||
// Picotool binary info metadata
|
||||
|
||||
@@ -382,4 +382,24 @@ pub(crate) fn poll_sensor(
|
||||
delay.delay_ms(POLL_MS);
|
||||
}
|
||||
|
||||
/// Initialise all peripherals and run the DHT11 sensor demo.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `pac` - PAC Peripherals singleton (consumed).
|
||||
pub(crate) fn run(mut pac: hal::pac::Peripherals) -> ! {
|
||||
let mut wd = hal::Watchdog::new(pac.WATCHDOG);
|
||||
let clocks = init_clocks(pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS, &mut wd);
|
||||
let pins = init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS);
|
||||
let uart = init_uart(pac.UART0, pins.gpio0, pins.gpio1, &mut pac.RESETS, &clocks);
|
||||
let mut delay = init_delay(&clocks);
|
||||
#[cfg(rp2350)]
|
||||
let timer = hal::Timer::new_timer0(pac.TIMER0, &mut pac.RESETS, &clocks);
|
||||
#[cfg(rp2040)]
|
||||
let timer = hal::Timer::new(pac.TIMER, &mut pac.RESETS);
|
||||
let _ = pins.gpio4.into_pull_up_input();
|
||||
uart.write_full_blocking(b"DHT11 driver initialized on GPIO 4\r\n");
|
||||
loop { poll_sensor(&uart, &timer, &mut delay); }
|
||||
}
|
||||
|
||||
// End of file
|
||||
|
||||
@@ -111,21 +111,20 @@ pub fn parse_temperature(data: &[u8; 5]) -> f32 {
|
||||
///
|
||||
/// Number of bytes written into the buffer.
|
||||
pub fn format_reading(buf: &mut [u8], humidity: f32, temperature: f32) -> usize {
|
||||
let mut pos = 0;
|
||||
let prefix = b"Humidity: ";
|
||||
buf[pos..pos + prefix.len()].copy_from_slice(prefix);
|
||||
pos += prefix.len();
|
||||
let mut pos = copy_slice(buf, 0, b"Humidity: ");
|
||||
pos += format_f32_1(&mut buf[pos..], humidity);
|
||||
let mid = b"% Temperature: ";
|
||||
buf[pos..pos + mid.len()].copy_from_slice(mid);
|
||||
pos += mid.len();
|
||||
pos += copy_slice(buf, pos, b"% Temperature: ");
|
||||
pos += format_f32_1(&mut buf[pos..], temperature);
|
||||
let suffix = b" C";
|
||||
buf[pos..pos + suffix.len()].copy_from_slice(suffix);
|
||||
pos += suffix.len();
|
||||
pos += copy_slice(buf, pos, b" C");
|
||||
pos
|
||||
}
|
||||
|
||||
/// Copy a byte slice into `buf` at the given offset, returning bytes written.
|
||||
fn copy_slice(buf: &mut [u8], offset: usize, src: &[u8]) -> usize {
|
||||
buf[offset..offset + src.len()].copy_from_slice(src);
|
||||
src.len()
|
||||
}
|
||||
|
||||
/// Format a failed-read error message.
|
||||
///
|
||||
/// # Arguments
|
||||
@@ -185,17 +184,7 @@ fn format_f32_1(buf: &mut [u8], val: f32) -> usize {
|
||||
let scaled = (val * 10.0) as u32;
|
||||
let integer = scaled / 10;
|
||||
let frac = (scaled % 10) as u8;
|
||||
let mut pos = 0;
|
||||
if integer >= 100 {
|
||||
buf[pos] = b'0' + (integer / 100) as u8;
|
||||
pos += 1;
|
||||
}
|
||||
if integer >= 10 {
|
||||
buf[pos] = b'0' + ((integer / 10) % 10) as u8;
|
||||
pos += 1;
|
||||
}
|
||||
buf[pos] = b'0' + (integer % 10) as u8;
|
||||
pos += 1;
|
||||
let mut pos = format_u32_minimal(buf, integer);
|
||||
buf[pos] = b'.';
|
||||
pos += 1;
|
||||
buf[pos] = b'0' + frac;
|
||||
@@ -203,6 +192,21 @@ fn format_f32_1(buf: &mut [u8], val: f32) -> usize {
|
||||
pos
|
||||
}
|
||||
|
||||
/// Format a u32 as minimal decimal digits (no leading zeros).
|
||||
fn format_u32_minimal(buf: &mut [u8], value: u32) -> usize {
|
||||
let mut pos = 0;
|
||||
if value >= 100 {
|
||||
buf[pos] = b'0' + (value / 100) as u8;
|
||||
pos += 1;
|
||||
}
|
||||
if value >= 10 {
|
||||
buf[pos] = b'0' + ((value / 10) % 10) as u8;
|
||||
pos += 1;
|
||||
}
|
||||
buf[pos] = b'0' + (value % 10) as u8;
|
||||
pos + 1
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
// Import all parent module items
|
||||
|
||||
@@ -78,32 +78,9 @@ pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
|
||||
pub static IMAGE_DEF: hal::block::ImageDef = hal::block::ImageDef::secure_exe();
|
||||
|
||||
/// Application entry point for the DHT11 sensor demo.
|
||||
///
|
||||
/// Initializes the DHT11 on GPIO4 and continuously reads temperature
|
||||
/// and humidity, printing results over UART every 2 seconds.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Does not return.
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let mut pac = hal::pac::Peripherals::take().unwrap();
|
||||
let clocks = board::init_clocks(
|
||||
pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS,
|
||||
&mut hal::Watchdog::new(pac.WATCHDOG),
|
||||
);
|
||||
let pins = board::init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS);
|
||||
let uart = board::init_uart(pac.UART0, pins.gpio0, pins.gpio1, &mut pac.RESETS, &clocks);
|
||||
let mut delay = board::init_delay(&clocks);
|
||||
#[cfg(rp2350)]
|
||||
let timer = hal::Timer::new_timer0(pac.TIMER0, &mut pac.RESETS, &clocks);
|
||||
#[cfg(rp2040)]
|
||||
let timer = hal::Timer::new(pac.TIMER, &mut pac.RESETS);
|
||||
let _dht_pin = pins.gpio4.into_pull_up_input();
|
||||
uart.write_full_blocking(b"DHT11 driver initialized on GPIO 4\r\n");
|
||||
loop {
|
||||
board::poll_sensor(&uart, &timer, &mut delay);
|
||||
}
|
||||
board::run(hal::pac::Peripherals::take().unwrap())
|
||||
}
|
||||
|
||||
// Picotool binary info metadata
|
||||
|
||||
@@ -216,4 +216,36 @@ pub(crate) fn poll_receiver(
|
||||
uart.write_full_blocking(&buf[..len]);
|
||||
}
|
||||
delay.delay_ms(POLL_MS);
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialise all peripherals and run the NEC IR receiver demo.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `pac` - PAC Peripherals singleton (consumed).
|
||||
pub(crate) fn run(mut pac: hal::pac::Peripherals) -> ! {
|
||||
let mut wd = hal::Watchdog::new(pac.WATCHDOG);
|
||||
let clocks = init_clocks(pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS, &mut wd);
|
||||
let pins = init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS);
|
||||
let uart = init_uart(pac.UART0, pins.gpio0, pins.gpio1, &mut pac.RESETS, &clocks);
|
||||
let mut delay = init_delay(&clocks);
|
||||
#[cfg(rp2350)]
|
||||
let timer = hal::Timer::new_timer0(pac.TIMER0, &mut pac.RESETS, &clocks);
|
||||
#[cfg(rp2040)]
|
||||
let timer = hal::Timer::new(pac.TIMER, &mut pac.RESETS);
|
||||
let _ = pins.gpio5.into_pull_up_input();
|
||||
announce_ir(&uart);
|
||||
loop { poll_receiver(&uart, &timer, &mut delay); }
|
||||
}
|
||||
|
||||
/// Print the IR driver initialisation banner over UART.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `uart` - Reference to the enabled UART peripheral for serial output.
|
||||
fn announce_ir(uart: &EnabledUart) {
|
||||
uart.write_full_blocking(b"NEC IR driver initialized on GPIO 5\r\n");
|
||||
uart.write_full_blocking(b"Press a button on your NEC remote...\r\n");
|
||||
}
|
||||
|
||||
// End of file
|
||||
@@ -98,39 +98,38 @@ pub fn validate_nec_frame(data: &[u8; 4]) -> Option<u8> {
|
||||
|
||||
/// Format the decoded command as hexadecimal and decimal followed by CRLF.
|
||||
pub fn format_command(buf: &mut [u8], command: u8) -> usize {
|
||||
let mut pos = 0;
|
||||
let prefix = b"NEC command: 0x";
|
||||
buf[pos..pos + prefix.len()].copy_from_slice(prefix);
|
||||
pos += prefix.len();
|
||||
let mut pos = copy_slice(buf, 0, prefix);
|
||||
pos += format_hex_u8(buf, pos, command);
|
||||
let middle = b" (";
|
||||
buf[pos..pos + middle.len()].copy_from_slice(middle);
|
||||
pos += middle.len();
|
||||
pos += copy_slice(buf, pos, b" (");
|
||||
pos += format_u8(buf, pos, command);
|
||||
buf[pos] = b')';
|
||||
pos += 1;
|
||||
buf[pos] = b'\r';
|
||||
pos += 1;
|
||||
buf[pos] = b'\n';
|
||||
pos += 1;
|
||||
pos += copy_slice(buf, pos, b")\r\n");
|
||||
pos
|
||||
}
|
||||
|
||||
/// Copy a byte slice into `buf` at the given offset, returning bytes written.
|
||||
fn copy_slice(buf: &mut [u8], offset: usize, src: &[u8]) -> usize {
|
||||
buf[offset..offset + src.len()].copy_from_slice(src);
|
||||
src.len()
|
||||
}
|
||||
|
||||
/// Format an unsigned 8-bit integer at the given buffer offset.
|
||||
fn format_u8(buf: &mut [u8], pos: usize, value: u8) -> usize {
|
||||
if value >= 100 {
|
||||
buf[pos] = b'0' + value / 100;
|
||||
buf[pos + 1] = b'0' + (value / 10) % 10;
|
||||
buf[pos + 2] = b'0' + value % 10;
|
||||
3
|
||||
} else if value >= 10 {
|
||||
buf[pos] = b'0' + value / 10;
|
||||
buf[pos + 1] = b'0' + value % 10;
|
||||
2
|
||||
} else {
|
||||
buf[pos] = b'0' + value;
|
||||
1
|
||||
}
|
||||
let n = u8_digit_count(value);
|
||||
write_u8_digits(buf, pos, value, n);
|
||||
n
|
||||
}
|
||||
|
||||
/// Return the number of decimal digits in a u8.
|
||||
fn u8_digit_count(value: u8) -> usize {
|
||||
if value >= 100 { 3 } else if value >= 10 { 2 } else { 1 }
|
||||
}
|
||||
|
||||
/// Write the decimal digits of a u8 into `buf` at `pos`.
|
||||
fn write_u8_digits(buf: &mut [u8], pos: usize, value: u8, n: usize) {
|
||||
if n >= 3 { buf[pos] = b'0' + value / 100; }
|
||||
if n >= 2 { buf[pos + n - 2] = b'0' + (value / 10) % 10; }
|
||||
buf[pos + n - 1] = b'0' + value % 10;
|
||||
}
|
||||
|
||||
/// Format an unsigned 8-bit integer as two uppercase hexadecimal digits.
|
||||
|
||||
@@ -79,24 +79,7 @@ pub static IMAGE_DEF: hal::block::ImageDef = hal::block::ImageDef::secure_exe();
|
||||
/// Application entry point for the NEC IR receiver demo.
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let mut pac = hal::pac::Peripherals::take().unwrap();
|
||||
let clocks = board::init_clocks(
|
||||
pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS,
|
||||
&mut hal::Watchdog::new(pac.WATCHDOG),
|
||||
);
|
||||
let pins = board::init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS);
|
||||
let uart = board::init_uart(pac.UART0, pins.gpio0, pins.gpio1, &mut pac.RESETS, &clocks);
|
||||
let mut delay = board::init_delay(&clocks);
|
||||
#[cfg(rp2350)]
|
||||
let timer = hal::Timer::new_timer0(pac.TIMER0, &mut pac.RESETS, &clocks);
|
||||
#[cfg(rp2040)]
|
||||
let timer = hal::Timer::new(pac.TIMER, &mut pac.RESETS);
|
||||
let _ir_pin = pins.gpio5.into_pull_up_input();
|
||||
uart.write_full_blocking(b"NEC IR driver initialized on GPIO 5\r\n");
|
||||
uart.write_full_blocking(b"Press a button on your NEC remote...\r\n");
|
||||
loop {
|
||||
board::poll_receiver(&uart, &timer, &mut delay);
|
||||
}
|
||||
board::run(hal::pac::Peripherals::take().unwrap())
|
||||
}
|
||||
|
||||
// Picotool binary info metadata
|
||||
|
||||
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -196,4 +196,24 @@ pub(crate) fn loopback_transfer(
|
||||
uart.write_full_blocking(&line_buf[..rx_len]);
|
||||
spi::clear_rx_buffer(&mut rx);
|
||||
delay.delay_ms(POLL_MS);
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialise all peripherals and run the SPI loopback demo.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `pac` - PAC Peripherals singleton (consumed).
|
||||
pub(crate) fn run(mut pac: hal::pac::Peripherals) -> ! {
|
||||
let mut wd = hal::Watchdog::new(pac.WATCHDOG);
|
||||
let clocks = init_clocks(pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS, &mut wd);
|
||||
let pins = init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS);
|
||||
let uart = init_uart(pac.UART0, pins.gpio0, pins.gpio1, &mut pac.RESETS, &clocks);
|
||||
let mut delay = init_delay(&clocks);
|
||||
let (mut spi, mut cs) = init_spi(
|
||||
pac.SPI0, pins.gpio16, pins.gpio17, pins.gpio18, pins.gpio19, &mut pac.RESETS, &clocks,
|
||||
);
|
||||
uart.write_full_blocking(b"SPI driver initialized on SPI0 at 1000000 Hz\r\n");
|
||||
loop { loopback_transfer(&mut spi, &mut cs, &uart, &mut delay); }
|
||||
}
|
||||
|
||||
// End of file
|
||||
@@ -78,27 +78,7 @@ pub static IMAGE_DEF: hal::block::ImageDef = hal::block::ImageDef::secure_exe();
|
||||
/// Application entry point for the SPI loopback demo.
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let mut pac = hal::pac::Peripherals::take().unwrap();
|
||||
let clocks = board::init_clocks(
|
||||
pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS,
|
||||
&mut hal::Watchdog::new(pac.WATCHDOG),
|
||||
);
|
||||
let pins = board::init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS);
|
||||
let uart = board::init_uart(pac.UART0, pins.gpio0, pins.gpio1, &mut pac.RESETS, &clocks);
|
||||
let mut delay = board::init_delay(&clocks);
|
||||
let (mut spi_dev, mut cs) = board::init_spi(
|
||||
pac.SPI0,
|
||||
pins.gpio16,
|
||||
pins.gpio17,
|
||||
pins.gpio18,
|
||||
pins.gpio19,
|
||||
&mut pac.RESETS,
|
||||
&clocks,
|
||||
);
|
||||
uart.write_full_blocking(b"SPI driver initialized on SPI0 at 1000000 Hz\r\n");
|
||||
loop {
|
||||
board::loopback_transfer(&mut spi_dev, &mut cs, &uart, &mut delay);
|
||||
}
|
||||
board::run(hal::pac::Peripherals::take().unwrap())
|
||||
}
|
||||
|
||||
// Picotool binary info metadata
|
||||
|
||||
@@ -77,22 +77,25 @@ fn format_line(buf: &mut [u8], prefix: &[u8], text: &[u8], extra_blank_line: boo
|
||||
let mut pos = 0;
|
||||
buf[pos..pos + prefix.len()].copy_from_slice(prefix);
|
||||
pos += prefix.len();
|
||||
let text_len = c_string_len(text);
|
||||
buf[pos..pos + text_len].copy_from_slice(&text[..text_len]);
|
||||
pos += text_len;
|
||||
buf[pos] = b'\r';
|
||||
pos += 1;
|
||||
buf[pos] = b'\n';
|
||||
pos += 1;
|
||||
if extra_blank_line {
|
||||
buf[pos] = b'\r';
|
||||
pos += 1;
|
||||
buf[pos] = b'\n';
|
||||
pos += 1;
|
||||
}
|
||||
pos += copy_c_string(&mut buf[pos..], text);
|
||||
pos += append_crlf(&mut buf[pos..], extra_blank_line);
|
||||
pos
|
||||
}
|
||||
|
||||
/// Copy bytes from `text` up to the first NUL into `buf`.
|
||||
fn copy_c_string(buf: &mut [u8], text: &[u8]) -> usize {
|
||||
let len = c_string_len(text);
|
||||
buf[..len].copy_from_slice(&text[..len]);
|
||||
len
|
||||
}
|
||||
|
||||
/// Append CRLF (and optionally a second blank CRLF) to `buf`.
|
||||
fn append_crlf(buf: &mut [u8], extra: bool) -> usize {
|
||||
buf[0] = b'\r';
|
||||
buf[1] = b'\n';
|
||||
if extra { buf[2] = b'\r'; buf[3] = b'\n'; 4 } else { 2 }
|
||||
}
|
||||
|
||||
/// Return the length up to the first NUL byte or full slice length.
|
||||
fn c_string_len(text: &[u8]) -> usize {
|
||||
let mut len = 0usize;
|
||||
|
||||
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -165,3 +165,21 @@ pub(crate) fn send_and_print(
|
||||
*counter = counter.wrapping_add(1);
|
||||
delay.delay_ms(POLL_MS);
|
||||
}
|
||||
|
||||
/// Initialise all peripherals and run the multicore FIFO demo.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `pac` - PAC Peripherals singleton (consumed).
|
||||
pub(crate) fn run(mut pac: hal::pac::Peripherals) -> ! {
|
||||
let mut wd = hal::Watchdog::new(pac.WATCHDOG);
|
||||
let clocks = init_clocks(pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS, &mut wd);
|
||||
let (pins, mut fifo) = init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS);
|
||||
let uart = init_uart(pac.UART0, pins.gpio0, pins.gpio1, &mut pac.RESETS, &clocks);
|
||||
let mut delay = init_delay(&clocks);
|
||||
spawn_core1(&mut pac.PSM, &mut pac.PPB, &mut fifo);
|
||||
let mut counter = 0u32;
|
||||
loop { send_and_print(&mut fifo, &uart, &mut counter, &mut delay); }
|
||||
}
|
||||
|
||||
// End of file
|
||||
|
||||
@@ -76,21 +76,7 @@ pub static IMAGE_DEF: hal::block::ImageDef = hal::block::ImageDef::secure_exe();
|
||||
/// Application entry point for the multicore FIFO demo.
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let mut pac = hal::pac::Peripherals::take().unwrap();
|
||||
let clocks = board::init_clocks(
|
||||
pac.XOSC, pac.CLOCKS, pac.PLL_SYS, pac.PLL_USB, &mut pac.RESETS,
|
||||
&mut hal::Watchdog::new(pac.WATCHDOG),
|
||||
);
|
||||
let (pins, mut fifo) = board::init_pins(
|
||||
pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS,
|
||||
);
|
||||
let uart = board::init_uart(pac.UART0, pins.gpio0, pins.gpio1, &mut pac.RESETS, &clocks);
|
||||
let mut delay = board::init_delay(&clocks);
|
||||
board::spawn_core1(&mut pac.PSM, &mut pac.PPB, &mut fifo);
|
||||
let mut counter = 0u32;
|
||||
loop {
|
||||
board::send_and_print(&mut fifo, &uart, &mut counter, &mut delay);
|
||||
}
|
||||
board::run(hal::pac::Peripherals::take().unwrap())
|
||||
}
|
||||
|
||||
// Picotool binary info metadata
|
||||
|
||||
@@ -37,17 +37,27 @@ fn format_u32(buf: &mut [u8], value: u32) -> usize {
|
||||
return 1;
|
||||
}
|
||||
let mut tmp = [0u8; 10];
|
||||
let mut pos = 0usize;
|
||||
let mut v = value;
|
||||
while v > 0 {
|
||||
tmp[pos] = b'0' + (v % 10) as u8;
|
||||
v /= 10;
|
||||
pos += 1;
|
||||
let n = u32_to_digits_reversed(&mut tmp, value);
|
||||
reverse_copy(buf, &tmp, n);
|
||||
n
|
||||
}
|
||||
|
||||
/// Convert a u32 to reversed decimal digits in a temporary buffer.
|
||||
fn u32_to_digits_reversed(tmp: &mut [u8; 10], mut value: u32) -> usize {
|
||||
let mut n = 0usize;
|
||||
while value > 0 {
|
||||
tmp[n] = b'0' + (value % 10) as u8;
|
||||
value /= 10;
|
||||
n += 1;
|
||||
}
|
||||
for i in 0..pos {
|
||||
buf[i] = tmp[pos - 1 - i];
|
||||
n
|
||||
}
|
||||
|
||||
/// Copy digits from a reversed temporary buffer into the output buffer.
|
||||
fn reverse_copy(buf: &mut [u8], tmp: &[u8], n: usize) {
|
||||
for i in 0..n {
|
||||
buf[i] = tmp[n - 1 - i];
|
||||
}
|
||||
pos
|
||||
}
|
||||
|
||||
/// Format the round-trip message for UART output.
|
||||
|
||||
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user