Skip to content

Commit 275d0e8

Browse files
committed
examples(pygamer): Restore neopixel examples using SPI driver
1 parent 8243da6 commit 275d0e8

File tree

7 files changed

+547
-1
lines changed

7 files changed

+547
-1
lines changed

boards/pygamer/Cargo.toml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ version = "0.20.0"
3333
optional = true
3434
version = "0.3.2"
3535

36+
[dependencies.ws2812-spi]
37+
version = "0.5.0"
38+
features = ["mosi_idle_high"]
39+
optional = true
40+
3641
[dev-dependencies]
3742
embedded-graphics = "0.8.1"
3843
embedded-sdmmc = "0.8.0"
@@ -52,6 +57,7 @@ max-channels = ["dma", "atsamd-hal/max-channels"]
5257
panic_led = []
5358
rt = ["cortex-m-rt", "atsamd-hal/samd51j-rt"]
5459
usb = ["atsamd-hal/usb", "usb-device"]
60+
neopixel-spi = ["dep:ws2812-spi"]
5561
# Enable async support from atsamd-hal
5662
async = ["atsamd-hal/async"]
5763

@@ -89,3 +95,23 @@ name = "timer"
8995
[[example]]
9096
name = "usb_poll"
9197
required-features = ["usb"]
98+
99+
[[example]]
100+
name = "neopixel_adc_battery"
101+
required-features = ["neopixel-spi"]
102+
103+
[[example]]
104+
name = "neopixel_adc_light"
105+
required-features = ["neopixel-spi"]
106+
107+
[[example]]
108+
name = "neopixel_button"
109+
required-features = ["neopixel-spi"]
110+
111+
[[example]]
112+
name = "neopixel_easing"
113+
required-features = ["neopixel-spi"]
114+
115+
[[example]]
116+
name = "neopixel_rainbow"
117+
required-features = ["neopixel-spi"]
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
//! Display battery percentage on the neopixels.
2+
//!
3+
//! Note leds may appear white during debug. Either build for release or add
4+
//! opt-level = 2 to profile.dev in Cargo.toml
5+
6+
#![no_std]
7+
#![no_main]
8+
9+
#[cfg(not(feature = "panic_led"))]
10+
use panic_halt as _;
11+
use pygamer::{entry, hal, pac, Pins};
12+
13+
use hal::adc::Adc;
14+
use hal::{clock::GenericClockController, delay::Delay};
15+
16+
use pac::gclk::pchctrl::Genselect::Gclk11;
17+
18+
use hal::ehal::delay::DelayNs;
19+
20+
use pac::{CorePeripherals, Peripherals};
21+
use smart_leds::{brightness, SmartLedsWrite, RGB8};
22+
23+
#[entry]
24+
fn main() -> ! {
25+
let mut peripherals = Peripherals::take().unwrap();
26+
let core = CorePeripherals::take().unwrap();
27+
let mut clocks = GenericClockController::with_internal_32kosc(
28+
peripherals.gclk,
29+
&mut peripherals.mclk,
30+
&mut peripherals.osc32kctrl,
31+
&mut peripherals.oscctrl,
32+
&mut peripherals.nvmctrl,
33+
);
34+
let pins = Pins::new(peripherals.port).split();
35+
36+
let mut adc0 = Adc::adc0(peripherals.adc0, &mut peripherals.mclk, &mut clocks, Gclk11);
37+
let mut battery = pins.battery.init();
38+
39+
// neopixels
40+
let mut neopixel = pins.neopixel.init_spi(
41+
&mut clocks,
42+
// Unfortunately, the SPI driver requires a clock pin, even though it's not used by the
43+
// neopixels.
44+
pins.i2c.scl,
45+
peripherals.sercom2,
46+
&mut peripherals.mclk,
47+
);
48+
49+
let mut delay = Delay::new(core.SYST, &mut clocks);
50+
51+
//todo put this on a .. 10minute, 30min, update timer
52+
loop {
53+
let battery_data = battery.read(&mut adc0);
54+
55+
let mut colors = [
56+
RGB8::default(),
57+
RGB8::default(),
58+
RGB8::default(),
59+
RGB8::default(),
60+
RGB8::default(),
61+
];
62+
63+
if battery_data < 3.6 {
64+
enable_leds(1, &mut colors);
65+
} else if (3.6..3.8).contains(&battery_data) {
66+
enable_leds(2, &mut colors);
67+
} else if (3.8..3.9).contains(&battery_data) {
68+
enable_leds(3, &mut colors);
69+
} else if (3.9..4.0).contains(&battery_data) {
70+
enable_leds(4, &mut colors);
71+
} else {
72+
enable_leds(5, &mut colors);
73+
};
74+
75+
neopixel
76+
.write(brightness(colors.iter().cloned(), 1))
77+
.unwrap();
78+
79+
// Reset the LEDs
80+
delay.delay_ms(10);
81+
}
82+
}
83+
84+
/// Turn on the specified number of LEDs and set the color to red.
85+
fn enable_leds(num_leds: usize, colors: &mut [RGB8]) {
86+
for color in colors.iter_mut().take(num_leds) {
87+
*color = RGB8::from((255, 0, 0));
88+
}
89+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
//! Display light sensor reading on the neopixels.
2+
//!
3+
//! Note leds may appear white during debug. Either build for release or add
4+
//! opt-level = 2 to profile.dev in Cargo.toml
5+
6+
#![no_std]
7+
#![no_main]
8+
9+
#[cfg(not(feature = "panic_led"))]
10+
use panic_halt as _;
11+
use pygamer::{entry, hal, pac, Pins};
12+
13+
use hal::adc::Adc;
14+
use hal::prelude::*;
15+
use hal::{clock::GenericClockController, delay::Delay};
16+
use pac::gclk::pchctrl::Genselect::Gclk11;
17+
use pac::{CorePeripherals, Peripherals};
18+
use smart_leds::SmartLedsWrite;
19+
use smart_leds::{
20+
hsv::{hsv2rgb, Hsv},
21+
RGB8,
22+
};
23+
24+
#[entry]
25+
fn main() -> ! {
26+
let mut peripherals = Peripherals::take().unwrap();
27+
let core = CorePeripherals::take().unwrap();
28+
let mut clocks = GenericClockController::with_internal_32kosc(
29+
peripherals.gclk,
30+
&mut peripherals.mclk,
31+
&mut peripherals.osc32kctrl,
32+
&mut peripherals.oscctrl,
33+
&mut peripherals.nvmctrl,
34+
);
35+
let pins = Pins::new(peripherals.port).split();
36+
37+
let mut adc1 = Adc::adc1(peripherals.adc1, &mut peripherals.mclk, &mut clocks, Gclk11);
38+
let mut light = pins.light_pin.into_alternate();
39+
40+
// neopixels
41+
let mut neopixel = pins.neopixel.init_spi(
42+
&mut clocks,
43+
// Unfortunately, the SPI driver requires a clock pin, even though it's not used by the
44+
// neopixels.
45+
pins.i2c.scl,
46+
peripherals.sercom2,
47+
&mut peripherals.mclk,
48+
);
49+
50+
let mut delay = Delay::new(core.SYST, &mut clocks);
51+
52+
const NUM_LEDS: usize = 5;
53+
let mut j: u8 = 0;
54+
55+
loop {
56+
let light_data: u16 = adc1.read(&mut light).unwrap();
57+
58+
let pos: usize = if light_data < 100 {
59+
0
60+
} else if (147..1048).contains(&light_data) {
61+
1
62+
} else if (1048..3048).contains(&light_data) {
63+
2
64+
} else if (3048..3948).contains(&light_data) {
65+
3
66+
} else {
67+
4
68+
};
69+
70+
//finally paint the one led wherever the position is
71+
let _ = neopixel.write((0..NUM_LEDS).map(|i| {
72+
if i == pos {
73+
hsv2rgb(Hsv {
74+
hue: j,
75+
sat: 255,
76+
val: 32,
77+
})
78+
} else {
79+
RGB8::default()
80+
}
81+
}));
82+
83+
//incremement the hue easing
84+
j = j.wrapping_add(1);
85+
86+
delay.delay_ms(10u8);
87+
}
88+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
//! Joystick y controls the color of a neopixel while Joystick x moves it
2+
//! left and right around the center neopixel
3+
//! Select and Start control a second neopixel left and right while it is
4+
//! automatically rotating through the color wheel
5+
//! When they overlap, joystick takes precedence
6+
//!
7+
//! Note leds may appear white during debug. Either build for release or add
8+
//! opt-level = 2 to profile.dev in Cargo.toml
9+
10+
#![no_std]
11+
#![no_main]
12+
13+
#[cfg(not(feature = "panic_led"))]
14+
use panic_halt as _;
15+
use pygamer::{self as bsp, entry, hal, pac, pins::Keys, Pins};
16+
17+
use bsp::util::map_from;
18+
use hal::adc::Adc;
19+
use hal::{clock::GenericClockController, delay::Delay};
20+
21+
use pac::gclk::pchctrl::Genselect::Gclk11;
22+
use pac::{CorePeripherals, Peripherals};
23+
24+
use hal::ehal::delay::DelayNs;
25+
26+
use smart_leds::SmartLedsWrite;
27+
use smart_leds::{
28+
hsv::{hsv2rgb, Hsv},
29+
RGB8,
30+
};
31+
32+
#[entry]
33+
fn main() -> ! {
34+
let mut peripherals = Peripherals::take().unwrap();
35+
let core_peripherals = CorePeripherals::take().unwrap();
36+
37+
let mut clocks = GenericClockController::with_internal_32kosc(
38+
peripherals.gclk,
39+
&mut peripherals.mclk,
40+
&mut peripherals.osc32kctrl,
41+
&mut peripherals.oscctrl,
42+
&mut peripherals.nvmctrl,
43+
);
44+
45+
let mut delay = Delay::new(core_peripherals.SYST, &mut clocks);
46+
let pins = Pins::new(peripherals.port).split();
47+
48+
let mut buttons = pins.buttons.init();
49+
50+
let mut adc1 = Adc::adc1(peripherals.adc1, &mut peripherals.mclk, &mut clocks, Gclk11);
51+
let mut joystick = pins.joystick.init();
52+
53+
// neopixels
54+
let mut neopixel = pins.neopixel.init_spi(
55+
&mut clocks,
56+
// Unfortunately, the SPI driver requires a clock pin, even though it's not used by the
57+
// neopixels.
58+
pins.i2c.scl,
59+
peripherals.sercom2,
60+
&mut peripherals.mclk,
61+
);
62+
63+
const NUM_LEDS: usize = 5;
64+
let mut pos_button: usize = 2;
65+
let mut color_button: u8 = 0;
66+
loop {
67+
let (x, y) = joystick.read(&mut adc1);
68+
69+
// map up/down to control rainbow color 0-255
70+
let color_joy = map_from(y as i16, (0, 4095), (0, 255)) as u8;
71+
72+
// map left/right to neopixel position 0-4
73+
// joystick is not quite linear, rests at second pixel
74+
// shifting up by 500 seems to help
75+
let pos_joy = map_from(x as i16 + 500, (0, 4595), (0, 4)) as usize;
76+
77+
for event in buttons.events() {
78+
match event {
79+
Keys::SelectDown => {
80+
pos_button = pos_button.saturating_sub(1);
81+
}
82+
Keys::StartDown => {
83+
if pos_button < 4 {
84+
pos_button += 1;
85+
}
86+
}
87+
_ => {}
88+
}
89+
}
90+
91+
//finally paint the two leds at position, accel priority
92+
let _ = neopixel.write((0..NUM_LEDS).map(|i| {
93+
if i == pos_joy {
94+
hsv2rgb(Hsv {
95+
hue: color_joy,
96+
sat: 255,
97+
val: 32,
98+
})
99+
} else if i == pos_button {
100+
hsv2rgb(Hsv {
101+
hue: color_button,
102+
sat: 255,
103+
val: 32,
104+
})
105+
} else {
106+
RGB8::default()
107+
}
108+
}));
109+
110+
//incremement the hue easing
111+
color_button = color_button.wrapping_add(1);
112+
113+
delay.delay_ms(5);
114+
}
115+
}

0 commit comments

Comments
 (0)