Skip to content

Update the Pico2 example for more boards #57

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 28, 2024
Merged
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
4 changes: 2 additions & 2 deletions pico2-neopixel/Package.resolved
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"originHash" : "bcd9dd294c463af6cc0b00a78e58c705dd64d85ba22dabdedcb845394c3b8e0a",
"originHash" : "747e0fc02915a3002cb221ceea9473d78626a10186af199b6615f04105ad994a",
"pins" : [
{
"identity" : "swift-argument-parser",
Expand All @@ -16,7 +16,7 @@
"location" : "https://github.com/apple/swift-mmio.git",
"state" : {
"branch" : "swift-embedded-examples",
"revision" : "37ba05e16226deb1742d9fa4d115de3b564a9b4d"
"revision" : "275a877cbdd9d301a783425dbbccc630db364d37"
}
},
{
Expand Down
24 changes: 23 additions & 1 deletion pico2-neopixel/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,29 @@ An example project demonstrating how to drive a Neopixel RGB LED from an RP2350.

## Requirements

- SparkFun Pro Micro - RP2350 board. If you have another RP2350 board this example will require modifications.
- An RP2350 board, such as the "SparkFun Pro Micro - RP2350".

## Configuring

This example uses the hard coded constant `LED_PIN` in `Application.swift` to select the GPIO pin used to drive the attached Neopixel RGB LED. If you are using the "SparkFun Pro Micro - RP2350" no configuration is necessary, if you are using a different board you will need to adjust this constant to the pin used to drive your LED.

Example diff:

```diff
diff --git a/pico2-neopixel/Sources/Application/Application.swift b/pico2-neopixel/Sources/Application/Application.swift
index f6867b5..a2291db 100644
--- a/pico2-neopixel/Sources/Application/Application.swift
+++ b/pico2-neopixel/Sources/Application/Application.swift
@@ -11,7 +11,7 @@

import RP2350

-let LED_PIN: UInt32 = 25
+let LED_PIN: UInt32 = 18

/// Configures GPIO pin as a front-end to PIO0.
func configure_output_pin() {
```

## How to build and run this example:

Expand Down
36 changes: 16 additions & 20 deletions pico2-neopixel/Sources/Application/Application.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@

import RP2350

let LED_PIN: UInt32 = 25

/// Configures GPIO pin 25 as a front-end to PIO0.
func configure_output_pin() {
// Configure GPIO general properties
pads_bank0.gpio25.modify { rw in
pads_bank0.gpio[LED_PIN].modify { rw in
rw.raw.od = 0 // Enable output
rw.raw.ie = 0 // Disable input
rw.raw.pue = 1 // Disable pull up
Expand All @@ -24,12 +26,12 @@ func configure_output_pin() {
}

// Configure GPIO function selection to use PIO0
io_bank0.gpio25_ctrl.modify { rw in
io_bank0.gpio[LED_PIN].gpio_ctrl.modify { rw in
rw.raw.funcsel = 0x6 // Forward output from pio0 to this pin
}

// Remove pad isolation now that the correct peripheral is driving the pad
pads_bank0.gpio25.modify { rw in
pads_bank0.gpio[LED_PIN].modify { rw in
rw.raw.iso = 0 // Disable isolation
}
}
Expand All @@ -45,22 +47,16 @@ func configure_output_pin() {
/// `clkdiv_restart` to clear any persisted state.
func configure_pio() {
// Load the assembled program directly into the PIO's instruction memory.
//
// Ideally instr_mem would be an array but the svd2swift doesn't currently
// do that.
withUnsafeBytes(of: WS2812.pio_instructions) { pointer in
let pio_instructions = pointer.assumingMemoryBound(to: UInt16.self)
var instr_mem = pio0.instr_mem0
for pio_instr in pio_instructions {
instr_mem.write { w in
w.raw.instr_mem0_field = UInt32(pio_instr)
for (index, pio_instr) in pio_instructions.enumerated() {
pio0.instr_mem[index].write { w in
w.raw.instr_mem0 = UInt32(pio_instr)
}
// Unsafely move to the next instr_mem address.
instr_mem.unsafeAddress += 0x4
}

// Configure the PIO program wrap boundaries.
pio0.sm0_execctrl.modify { r, w in
pio0.sm[0].sm_execctrl.modify { r, w in
w.raw.wrap_bottom = 1 // Continue at 1
w.raw.wrap_top = UInt32(pio_instructions.count - 1) // Wrap after last.
}
Expand All @@ -82,7 +78,7 @@ func configure_pio() {
//
// int: floor(1.375) = 1
// frac: floor(0.375 * 255) = 95
pio0.sm0_clkdiv.write { rw in
pio0.sm[0].sm_clkdiv.write { rw in
rw.raw.int = 1
rw.raw.frac = 95
}
Expand All @@ -93,18 +89,18 @@ func configure_pio() {
// every 24 bits. If no data is in the txfifo, the state machine will stall.
// Additional bond the RX TX fifos into one larger TX fifo so we can buffer
// more pixel data.
pio0.sm0_shiftctrl.modify { rw in
pio0.sm[0].sm_shiftctrl.modify { rw in
rw.raw.autopull = 1 // Enable autopull
rw.raw.pull_thresh = 24 // 24 bit pull threshold
rw.raw.out_shiftdir = 0 // Left shift from OSR
rw.raw.fjoin_tx = 1 // Join RX TX fifos
}

// Setup the PIO state machine to output to the correct gpio pins.
pio0.sm0_pinctrl.modify { rw in
rw.raw.set_base = 25
pio0.sm[0].sm_pinctrl.modify { rw in
rw.raw.set_base = LED_PIN
rw.raw.set_count = 1
rw.raw.sideset_base = 25
rw.raw.sideset_base = LED_PIN
rw.raw.sideset_count = 1
}

Expand Down Expand Up @@ -132,8 +128,8 @@ func pio_write_pixel(_ hsv: HSV8Pixel) {
// Wait for the TX fifo to have space before writing to it.
while tx_fifo_full() { }
// Write the pixel value to TX fifo.
pio0.txf0.write { w in
w.raw.txf0_field = ws2812Value
pio0.txf[0].write { w in
w.raw.txf0 = ws2812Value
}
}

Expand Down
Loading