Using APA102 LEDs on SAMD11

I'm trying to talk to some APA102 (aka "DotStar") LEDs on an atsamd11c14a microcontroller.

I started out by combining this example of using SAMD11 with this example of using APA102. I had to change a few things, such as changing TC3 to TC1, and changing 5 kHz to 100 Hz. This is what I have now:

#![no_std]
#![no_main]

extern crate panic_halt;
extern crate samd11_bare as hal;

use apa102_spi as apa102;

use hal::clock::GenericClockController;
use hal::delay::Delay;
use hal::entry;
use hal::pac::{CorePeripherals, Peripherals};
use hal::prelude::*;
use hal::timer::TimerCounter;

use crate::apa102::Apa102;
use smart_leds_trait::RGB8;
use smart_leds::SmartLedsWrite;

#[entry]
fn main() -> ! {
    let mut peripherals = Peripherals::take().unwrap();
    let core = CorePeripherals::take().unwrap();

    let mut clocks = GenericClockController::with_internal_32kosc(
        peripherals.GCLK,
        &mut peripherals.PM,
        &mut peripherals.SYSCTRL,
        &mut peripherals.NVMCTRL,
    );

    let mut pins = hal::Pins::new(peripherals.PORT);
    let mut delay = Delay::new(core.SYST, &mut clocks);

    let di = pins.d2.into_push_pull_output(&mut pins.port);
    let ci = pins.d3.into_push_pull_output(&mut pins.port);
    let nc = pins.d14.into_floating_input(&mut pins.port);

    let gclk0 = clocks.gclk0();
    let timer_clock = clocks.tc1_tc2(&gclk0).unwrap();
    let mut timer = TimerCounter::tc1_(&timer_clock, peripherals.TC1, &mut peripherals.PM);
    timer.start(100.hz());

    let spi = bitbang_hal::spi::SPI::new(apa102_spi::MODE, nc, di, ci, timer);

    let mut dotstar = Apa102::new(spi);

    let state0: [RGB8; 1] = [RGB8 { r: 64, g: 0, b: 0 }];
    let state1: [RGB8; 1] = [RGB8 { r: 0, g: 64, b: 0 }];
    let state2: [RGB8; 1] = [RGB8 { r: 0, g: 0, b: 64 }];
    loop {
        dotstar.write(state0.iter().cloned()).unwrap();
        delay.delay_ms(1000 as u16);
        dotstar.write(state1.iter().cloned()).unwrap();
        delay.delay_ms(1000 as u16);
        dotstar.write(state2.iter().cloned()).unwrap();
        delay.delay_ms(1000 as u16);
    }
}

I'm getting the error message:

error[E0277]: the trait bound `hal::gpio::Pa4<hal::gpio::Input<hal::gpio::Floating>>: hal::prelude::_embedded_hal_digital_InputPin` is not satisfied
  --> src/main.rs:44:15
   |
44 |     let spi = bitbang_hal::spi::SPI::new(apa102_spi::MODE, nc, di, ci, timer);
   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `hal::prelude::_embedded_hal_digital_InputPin` is not implemented for `hal::gpio::Pa4<hal::gpio::Input<hal::gpio::Floating>>`
   |
   = note: required because of the requirements on the impl of `embedded_hal::digital::v2::InputPin` for `hal::gpio::Pa4<hal::gpio::Input<hal::gpio::Floating>>`
   = note: required by `bitbang_hal::spi::SPI::<Miso, Mosi, Sck, Timer>::new`

I'm having trouble figuring out how to fix this. Any suggestions? Thanks!

Never mind, I figured out that I needed to use the unproven feature of the samd11_bare crate. I successfully compiled my code with this Cargo.toml:

[dependencies]
apa102-spi = "0.3.2"
bitbang-hal = "0.3"
cortex-m = "0.6"
cortex-m-rt = "0.6"
embedded-hal = "0.2.3"
panic-halt = "0.2"
samd11_bare = { version = "0.3.0", features = ["unproven"]}
smart-leds = "0.3"
smart-leds-trait = "0.2"

For what it's worth, I eventually got it working with hardware SPI, too:

#![no_std]
#![no_main]

extern crate panic_halt;
extern crate samd11_bare as hal;

use apa102_spi as apa102;

use hal::clock::GenericClockController;
use hal::delay::Delay;
use hal::entry;
use hal::pac::{CorePeripherals, Peripherals};
use hal::pad::PadPin;
use hal::prelude::*;

use crate::apa102::Apa102;
use smart_leds_trait::RGB8;
use smart_leds::SmartLedsWrite;

const NUM_DOTSTAR: usize = 8;

#[entry]
fn main() -> ! {
    let mut peripherals = Peripherals::take().unwrap();
    let core = CorePeripherals::take().unwrap();

    let mut clocks = GenericClockController::with_internal_32kosc(
        peripherals.GCLK,
        &mut peripherals.PM,
        &mut peripherals.SYSCTRL,
        &mut peripherals.NVMCTRL,
    );

    let mut pins = hal::Pins::new(peripherals.PORT);
    let mut delay = Delay::new(core.SYST, &mut clocks);

    let gclk0 = clocks.gclk0();

    let spi: hal::sercom::SPIMaster0<
        hal::sercom::Sercom0Pad0<hal::gpio::Pa4<hal::gpio::PfD>>,
        hal::sercom::Sercom0Pad2<hal::gpio::Pa8<hal::gpio::PfD>>,
        hal::sercom::Sercom0Pad3<hal::gpio::Pa9<hal::gpio::PfD>>,
    > = hal::sercom::SPIMaster0::new(
        &clocks.sercom0_core(&gclk0).unwrap(),
        5000u32.hz(),
        apa102_spi::MODE,
        peripherals.SERCOM0,
        &mut peripherals.PM,
        (
            pins.d14.into_pad(&mut pins.port),
            pins.d2.into_pad(&mut pins.port),
            pins.d3.into_pad(&mut pins.port),
        ),
    );

    let mut dotstar = Apa102::new(spi);

    let state0: [RGB8; NUM_DOTSTAR] = [RGB8 { r: 64, g: 0, b: 0 }; NUM_DOTSTAR];
    let state1: [RGB8; NUM_DOTSTAR] = [RGB8 { r: 0, g: 64, b: 0 }; NUM_DOTSTAR];
    let state2: [RGB8; NUM_DOTSTAR] = [RGB8 { r: 0, g: 0, b: 64 }; NUM_DOTSTAR];
    loop {
        dotstar.write(state0.iter().cloned()).unwrap();
        delay.delay_ms(1000 as u16);
        dotstar.write(state1.iter().cloned()).unwrap();
        delay.delay_ms(1000 as u16);
        dotstar.write(state2.iter().cloned()).unwrap();
        delay.delay_ms(1000 as u16);
    }
}