pub fn new<SdaDisabledConfig: DisabledConfig, SclDisabledConfig: DisabledConfig>(
        pio: &'pio mut PIO<P>,
        sda: rp2040_hal::gpio::Pin<SDA, Disabled<SdaDisabledConfig>>,
        scl: rp2040_hal::gpio::Pin<SCL, Disabled<SclDisabledConfig>>,
        sm: UninitStateMachine<(P, SM)>,
        bus_freq: embedded_time::rate::Hertz,
        clock_freq: embedded_time::rate::Hertz,
    ) -> I2C<'pio, P, (P, SM), SDA, SCL>
    where
        Function<P>: ValidPinMode<SDA> + ValidPinMode<SCL>,
    {
        // prepare the PIO program
        let mut a = pio::Assembler::<32>::new_with_side_set(SIDESET);

        let mut handle_nack = a.label();
        let mut send_byte = a.label();
        let mut bitloop = a.label();
        let mut wrap_target = a.label();
        let mut wrap_source = a.label();
        let mut do_exec = a.label();

        a.bind(&mut &mut handle_nack);
        // continue if NAK was expected
        a.jmp(pio::JmpCondition::YDecNonZero, &mut wrap_target);
        // Otherwise stop, ask for help (raises the irq line (0+SM::id())%4)
        a.irq(false, true, 0, true);

        a.bind(&mut send_byte);
        // Unpack Final
        a.out(pio::OutDestination::Y, 1);
        // loop 8 times
        a.set(pio::SetDestination::X, 7);

        // Send 1 byte
        a.bind(&mut bitloop);
        // Serialize write data (all-ones is reading)
        a.out_with_delay(pio::OutDestination::PINDIRS, 1, 7);
        // SCL rising edge
        a.nop_with_delay_and_side_set(2, 1);
        // Allow clock to be stretched
        a.wait_with_delay(1, pio::WaitSource::GPIO, SCL::DYN.num, false, 4);
        // Sample read data in middle of SCL pulse
        a.in_with_delay(pio::InSource::PINS, 1, 7);
        // SCL falling edge
        a.jmp_with_delay_and_side_set(pio::JmpCondition::XDecNonZero, &mut bitloop, 7, 0);

        // handle ACK pulse
        // On reads, we provide the ACK
        a.out_with_delay(pio::OutDestination::PINDIRS, 1, 7);
        // SCL risin edge
        a.nop_with_delay_and_side_set(7, 1);
        // Allow clock to be stretched
        a.wait_with_delay(1, pio::WaitSource::GPIO, SCL::DYN.num, false, 7);
        // Test SDA for ACK/NACK, fall through if ACK
        a.jmp_with_delay_and_side_set(pio::JmpCondition::PinHigh, &mut handle_nack, 2, 0);

        a.bind(&mut wrap_target);
        // Unpack Instr count
        a.out(pio::OutDestination::X, 6);
        // Instr == 0, this is a data record
        a.jmp(pio::JmpCondition::XIsZero, &mut send_byte);
        // Instr > 0, remainder of this OSR is invalid
        a.out(pio::OutDestination::NULL, 32);

        a.bind(&mut do_exec);
        // Execute one instruction per FIFO word
        a.out(pio::OutDestination::EXEC, 16);
        a.jmp(pio::JmpCondition::XDecNonZero, &mut do_exec);
        a.bind(&mut wrap_source);

        let program = a.assemble_with_wrap(wrap_source, wrap_target);

        // Install the program into PIO instruction memory.
        let installed = pio.install(&program).unwrap();
        let wrap_target = installed.wrap_target();

        // Configure the PIO state machine.
        let div = clock_freq.integer() as f32 / (32.0 * bus_freq.integer() as f32);

        // init
        let (mut sm, rx, tx) = rp2040_hal::pio::PIOBuilder::from_program(installed)
            // use both RX & TX FIFO
            .buffers(rp2040_hal::pio::Buffers::RxTx)
            // Pin configuration
            .set_pins(SDA::DYN.num, 1)
            .out_pins(SDA::DYN.num, 1)
            .in_pin_base(SDA::DYN.num)
            .side_set_pin_base(SCL::DYN.num)
            .jmp_pin(SDA::DYN.num)
            // OSR config
            .out_shift_direction(rp2040_hal::pio::ShiftDirection::Left)
            .autopull(true)
            .pull_threshold(16)
            // ISR config
            .in_shift_direction(ShiftDirection::Left)
            .autopush(true)
            .push_threshold(8)
            // clock config
            .clock_divisor(div)
            .build(sm);

        // enable pull up on SDA & SCL: idle bus
        let sda = sda.into_pull_up_input();
        let scl = scl.into_pull_up_input();

        // This will pull the bus high for a little bit of time
        sm.set_pins([
            (SCL::DYN.num, PinState::High),
            (SDA::DYN.num, PinState::High),
        ]);
        sm.set_pindirs([
            (SCL::DYN.num, PinDir::Output),
            (SDA::DYN.num, PinDir::Output),
        ]);

        // attach SDA pin to pio
        let mut sda: Pin<SDA, Function<P>> = sda.into_mode();
        // configure SDA pin as inverted
        sda.set_output_enable_override(rp2040_hal::gpio::OutputEnableOverride::Invert);

        // attach SCL pin to pio
        let mut scl: Pin<SCL, Function<P>> = scl.into_mode();
        // configure SCL pin as inverted
        scl.set_output_enable_override(rp2040_hal::gpio::OutputEnableOverride::Invert);

        // the PIO now keeps the pin as Input, we can set the pin state to Low.
        sm.set_pins([(SDA::DYN.num, PinState::Low), (SCL::DYN.num, PinState::Low)]);

        // Set the state machine on the entry point.
        sm.exec_instruction(
            InstructionOperands::JMP {
                condition: pio::JmpCondition::Always,
                address: wrap_target,
            }
            .encode(),
        );

        // enable
        let sm = sm.start();

        Self {
            pio,
            sm,
            tx,
            rx,
            _sda: sda,
            _scl: scl,
        }
    }
/// Creates a new instance of this driver.
///
/// Note: the PIO must have been reset before using this driver.
Creates a new instance of this driver.
Note: the PIO must have been reset before using this driver.
Creates a new instance of this driver . Note : the PIO must have been reset before using this driver .
pub fn new<SdaDisabledConfig: DisabledConfig, SclDisabledConfig: DisabledConfig>(
        pio: &'pio mut PIO<P>,
        sda: rp2040_hal::gpio::Pin<SDA, Disabled<SdaDisabledConfig>>,
        scl: rp2040_hal::gpio::Pin<SCL, Disabled<SclDisabledConfig>>,
        sm: UninitStateMachine<(P, SM)>,
        bus_freq: embedded_time::rate::Hertz,
        clock_freq: embedded_time::rate::Hertz,
    ) -> I2C<'pio, P, (P, SM), SDA, SCL>
    where
        Function<P>: ValidPinMode<SDA> + ValidPinMode<SCL>,
    {
        // prepare the PIO program
        let mut a = pio::Assembler::<32>::new_with_side_set(SIDESET);
        let mut handle_nack = a.label();
        let mut send_byte = a.label();
        let mut bitloop = a.label();
        let mut wrap_target = a.label();
        let mut wrap_source = a.label();
        let mut do_exec = a.label();
        a.bind(&mut &mut handle_nack);
        // continue if NAK was expected
        a.jmp(pio::JmpCondition::YDecNonZero, &mut wrap_target);
        // Otherwise stop, ask for help (raises the irq line (0+SM::id())%4)
        a.irq(false, true, 0, true);
        a.bind(&mut send_byte);
        // Unpack Final
        a.out(pio::OutDestination::Y, 1);
        // loop 8 times
        a.set(pio::SetDestination::X, 7);
        // Send 1 byte
        a.bind(&mut bitloop);
        // Serialize write data (all-ones is reading)
        a.out_with_delay(pio::OutDestination::PINDIRS, 1, 7);
        // SCL rising edge
        a.nop_with_delay_and_side_set(2, 1);
        // Allow clock to be stretched
        a.wait_with_delay(1, pio::WaitSource::GPIO, SCL::DYN.num, false, 4);
        // Sample read data in middle of SCL pulse
        a.in_with_delay(pio::InSource::PINS, 1, 7);
        // SCL falling edge
        a.jmp_with_delay_and_side_set(pio::JmpCondition::XDecNonZero, &mut bitloop, 7, 0);
        // handle ACK pulse
        // On reads, we provide the ACK
        a.out_with_delay(pio::OutDestination::PINDIRS, 1, 7);
        // SCL risin edge
        a.nop_with_delay_and_side_set(7, 1);
        // Allow clock to be stretched
        a.wait_with_delay(1, pio::WaitSource::GPIO, SCL::DYN.num, false, 7);
        // Test SDA for ACK/NACK, fall through if ACK
        a.jmp_with_delay_and_side_set(pio::JmpCondition::PinHigh, &mut handle_nack, 2, 0);
        a.bind(&mut wrap_target);
        // Unpack Instr count
        a.out(pio::OutDestination::X, 6);
        // Instr == 0, this is a data record
        a.jmp(pio::JmpCondition::XIsZero, &mut send_byte);
        // Instr > 0, remainder of this OSR is invalid
        a.out(pio::OutDestination::NULL, 32);
        a.bind(&mut do_exec);
        // Execute one instruction per FIFO word
        a.out(pio::OutDestination::EXEC, 16);
        a.jmp(pio::JmpCondition::XDecNonZero, &mut do_exec);
        a.bind(&mut wrap_source);
        let program = a.assemble_with_wrap(wrap_source, wrap_target);
        // Install the program into PIO instruction memory.
        let installed = pio.install(&program).unwrap();
        let wrap_target = installed.wrap_target();
        // Configure the PIO state machine.
        let div = clock_freq.integer() as f32 / (32.0 * bus_freq.integer() as f32);
        // init
        let (mut sm, rx, tx) = rp2040_hal::pio::PIOBuilder::from_program(installed)
            // use both RX & TX FIFO
            .buffers(rp2040_hal::pio::Buffers::RxTx)
            // Pin configuration
            .set_pins(SDA::DYN.num, 1)
            .out_pins(SDA::DYN.num, 1)
            .in_pin_base(SDA::DYN.num)
            .side_set_pin_base(SCL::DYN.num)
            .jmp_pin(SDA::DYN.num)
            // OSR config
            .out_shift_direction(rp2040_hal::pio::ShiftDirection::Left)
            .autopull(true)
            .pull_threshold(16)
            // ISR config
            .in_shift_direction(ShiftDirection::Left)
            .autopush(true)
            .push_threshold(8)
            // clock config
            .clock_divisor(div)
            .build(sm);
        // enable pull up on SDA & SCL: idle bus
        let sda = sda.into_pull_up_input();
        let scl = scl.into_pull_up_input();
        // This will pull the bus high for a little bit of time
        sm.set_pins([
            (SCL::DYN.num, PinState::High),
            (SDA::DYN.num, PinState::High),
        ]);
        sm.set_pindirs([
            (SCL::DYN.num, PinDir::Output),
            (SDA::DYN.num, PinDir::Output),
        ]);
        // attach SDA pin to pio
        let mut sda: Pin<SDA, Function<P>> = sda.into_mode();
        // configure SDA pin as inverted
        sda.set_output_enable_override(rp2040_hal::gpio::OutputEnableOverride::Invert);
        // attach SCL pin to pio
        let mut scl: Pin<SCL, Function<P>> = scl.into_mode();
        // configure SCL pin as inverted
        scl.set_output_enable_override(rp2040_hal::gpio::OutputEnableOverride::Invert);
        // the PIO now keeps the pin as Input, we can set the pin state to Low.
        sm.set_pins([(SDA::DYN.num, PinState::Low), (SCL::DYN.num, PinState::Low)]);
        // Set the state machine on the entry point.
        sm.exec_instruction(
            InstructionOperands::JMP {
                condition: pio::JmpCondition::Always,
                address: wrap_target,
            }
            .encode(),
        );
        // enable
        let sm = sm.start();
        Self {
            pio,
            sm,
            tx,
            rx,
            _sda: sda,
            _scl: scl,
        }
    }
pub fn new < SdaDisabledConfig : DisabledConfig , SclDisabledConfig : DisabledConfig > ( pio : & ' pio mut PIO < P > , sda : rp2040_hal :: gpio :: Pin < SDA , Disabled < SdaDisabledConfig > > , scl : rp2040_hal :: gpio :: Pin < SCL , Disabled < SclDisabledConfig > > , sm : UninitStateMachine < ( P , SM ) > , bus_freq : embedded_time :: rate :: Hertz , clock_freq : embedded_time :: rate :: Hertz , ) -> I2C < ' pio , P , ( P , SM ) , SDA , SCL > where Function < P > : ValidPinMode < SDA > + ValidPinMode < SCL > , { // prepare the PIO program let mut a = pio :: Assembler :: < 32 > :: new_with_side_set ( SIDESET ) ; let mut handle_nack = a . label ( ) ; let mut send_byte = a . label ( ) ; let mut bitloop = a . label ( ) ; let mut wrap_target = a . label ( ) ; let mut wrap_source = a . label ( ) ; let mut do_exec = a . label ( ) ; a . bind ( & mut & mut handle_nack ) ; // continue if NAK was expected a . jmp ( pio :: JmpCondition :: YDecNonZero , & mut wrap_target ) ; // Otherwise stop, ask for help (raises the irq line (0+SM::id())%4) a . irq ( false , true , 0 , true ) ; a . bind ( & mut send_byte ) ; // Unpack Final a . out ( pio :: OutDestination :: Y , 1 ) ; // loop 8 times a . set ( pio :: SetDestination :: X , 7 ) ; // Send 1 byte a . bind ( & mut bitloop ) ; // Serialize write data (all-ones is reading) a . out_with_delay ( pio :: OutDestination :: PINDIRS , 1 , 7 ) ; // SCL rising edge a . nop_with_delay_and_side_set ( 2 , 1 ) ; // Allow clock to be stretched a . wait_with_delay ( 1 , pio :: WaitSource :: GPIO , SCL :: DYN . num , false , 4 ) ; // Sample read data in middle of SCL pulse a . in_with_delay ( pio :: InSource :: PINS , 1 , 7 ) ; // SCL falling edge a . jmp_with_delay_and_side_set ( pio :: JmpCondition :: XDecNonZero , & mut bitloop , 7 , 0 ) ; // handle ACK pulse // On reads, we provide the ACK a . out_with_delay ( pio :: OutDestination :: PINDIRS , 1 , 7 ) ; // SCL risin edge a . nop_with_delay_and_side_set ( 7 , 1 ) ; // Allow clock to be stretched a . wait_with_delay ( 1 , pio :: WaitSource :: GPIO , SCL :: DYN . num , false , 7 ) ; // Test SDA for ACK/NACK, fall through if ACK a . jmp_with_delay_and_side_set ( pio :: JmpCondition :: PinHigh , & mut handle_nack , 2 , 0 ) ; a . bind ( & mut wrap_target ) ; // Unpack Instr count a . out ( pio :: OutDestination :: X , 6 ) ; // Instr == 0, this is a data record a . jmp ( pio :: JmpCondition :: XIsZero , & mut send_byte ) ; // Instr > 0, remainder of this OSR is invalid a . out ( pio :: OutDestination :: NULL , 32 ) ; a . bind ( & mut do_exec ) ; // Execute one instruction per FIFO word a . out ( pio :: OutDestination :: EXEC , 16 ) ; a . jmp ( pio :: JmpCondition :: XDecNonZero , & mut do_exec ) ; a . bind ( & mut wrap_source ) ; let program = a . assemble_with_wrap ( wrap_source , wrap_target ) ; // Install the program into PIO instruction memory. let installed = pio . install ( & program ) . unwrap ( ) ; let wrap_target = installed . wrap_target ( ) ; // Configure the PIO state machine. let div = clock_freq . integer ( ) as f32 / ( 32.0 * bus_freq . integer ( ) as f32 ) ; // init let ( mut sm , rx , tx ) = rp2040_hal :: pio :: PIOBuilder :: from_program ( installed ) // use both RX & TX FIFO . buffers ( rp2040_hal :: pio :: Buffers :: RxTx ) // Pin configuration . set_pins ( SDA :: DYN . num , 1 ) . out_pins ( SDA :: DYN . num , 1 ) . in_pin_base ( SDA :: DYN . num ) . side_set_pin_base ( SCL :: DYN . num ) . jmp_pin ( SDA :: DYN . num ) // OSR config . out_shift_direction ( rp2040_hal :: pio :: ShiftDirection :: Left ) . autopull ( true ) . pull_threshold ( 16 ) // ISR config . in_shift_direction ( ShiftDirection :: Left ) . autopush ( true ) . push_threshold ( 8 ) // clock config . clock_divisor ( div ) . build ( sm ) ; // enable pull up on SDA & SCL: idle bus let sda = sda . into_pull_up_input ( ) ; let scl = scl . into_pull_up_input ( ) ; // This will pull the bus high for a little bit of time sm . set_pins ( [ ( SCL :: DYN . num , PinState :: High ) , ( SDA :: DYN . num , PinState :: High ) , ] ) ; sm . set_pindirs ( [ ( SCL :: DYN . num , PinDir :: Output ) , ( SDA :: DYN . num , PinDir :: Output ) , ] ) ; // attach SDA pin to pio let mut sda : Pin < SDA , Function < P > > = sda . into_mode ( ) ; // configure SDA pin as inverted sda . set_output_enable_override ( rp2040_hal :: gpio :: OutputEnableOverride :: Invert ) ; // attach SCL pin to pio let mut scl : Pin < SCL , Function < P > > = scl . into_mode ( ) ; // configure SCL pin as inverted scl . set_output_enable_override ( rp2040_hal :: gpio :: OutputEnableOverride :: Invert ) ; // the PIO now keeps the pin as Input, we can set the pin state to Low. sm . set_pins ( [ ( SDA :: DYN . num , PinState :: Low ) , ( SCL :: DYN . num , PinState :: Low ) ] ) ; // Set the state machine on the entry point. sm . exec_instruction ( InstructionOperands :: JMP { condition : pio :: JmpCondition :: Always , address : wrap_target , } . encode ( ) , ) ; // enable let sm = sm . start ( ) ; Self { pio , sm , tx , rx , _sda : sda , _scl : scl , } }
Creates a new instance of this driver.
Creates a new instance of this driver .
pio
&'pio mut PIO<P>
sda
rp2040_hal::gpio::Pin<SDA, Disabled<SdaDisabledConfig>>
scl
rp2040_hal::gpio::Pin<SCL, Disabled<SclDisabledConfig>>
sm
UninitStateMachine<(P, SM)>
bus_freq
embedded_time::rate::Hertz
clock_freq
embedded_time::rate::Hertz
pio
&'pio mut PIO<P>
sda
rp2040_hal::gpio::Pin<SDA, Disabled<SdaDisabledConfig>>
scl
rp2040_hal::gpio::Pin<SCL, Disabled<SclDisabledConfig>>
sm
UninitStateMachine<(P, SM)>
bus_freq
embedded_time::rate::Hertz
clock_freq
embedded_time::rate::Hertz