#ls7366 #quadrature-encoder

no-std ls7366

Rust interface to the LS7366 quadrature encoder buffer

3 unstable releases

0.2.1 May 14, 2020
0.2.0 May 2, 2020
0.1.0 May 1, 2020

29 downloads per month


670 lines

Rust interface to the SPI LS7366 Quadrature encoder buffer.

The full features of the chip have been implemented as per the docsheet, and are exposed by this driver.

This driver should work for any concrete embedded_hal::blocking::spi implementation.

Testing was done against a Dual LS7366R buffer chip On a RPi Model 4B.

Bonus Feature!

as of v0.2.0 the library is built with no_std.

See documentation for full driver details.

Building the quickstart:

The quickstart is desinged against rppal, and is intended to be run on a RPi. That said, it should be trivial enough to swap out the rppal elements for any other implementation.4B

cargo build --target=armv7-unknown-linux-gnueabihf --example quickstart


LS7366 Buffer encoder interface using embedded_hal.

This driver should work with any SPI interface as long as it implements the blocking embedded_hal SPI traits.

The library is built with no_std.


Bare-minimum boilerplate to read from the buffer:

  use ls7366::Ls7366;
// --- snip ---
# use std::error::Error;
# use rppal::spi::{Bus, Mode, SlaveSelect, Spi};
# use std::thread::sleep;
# use std::time::Duration;
# fn main() {
#    // create an instance of an SPI object
#    // In this case, the buffer is on SPI0 and SS1.
#    // The chip acts in Mode0.
#    let some_hal_spi_object = Spi::new(Bus::Spi0, SlaveSelect::Ss1, 14_000_000, Mode::Mode0).unwrap();
    // Construct a driver instance from the SPI interface, using default chip configurations.
    let mut spi_driver = Ls7366::new(some_hal_spi_object).unwrap();

    // Loop and read the counter.
    loop {
        let result = spi_driver.get_count().unwrap();
        println!("read data:= {:?}", result);
// --- snip ---
# }

Advanced configuration

The LS7366 has two registers dedicated to configuring the chip's various functions: Mdr0 and Mdr1.

Configuring the chip can be accomplished by writing into these two registers.

Manually configuring these registers is not required when using Ls7366::new.

  1. Build an instance of Mdr0 and Mdr1 with the desired configuration.
  2. Write these instances into the relevant registers.
use ls7366::mdr0::{QuadCountMode, CycleCountMode, FilterClockDivisionFactor,IndexMode, Mdr0};
use ls7366::mdr1::{CounterMode, Mdr1};
use ls7366::{Ls7366, Target, Encodable};
use embedded_hal_mock::spi::Mock;
use embedded_hal_mock::spi::Transaction as SpiTransaction;
# let expectations = [
#     SpiTransaction::write(vec![0b10001000, 0b10100110]),
#     SpiTransaction::write(vec![0b10010000, 0b00000101])
# ];
# let spi = Mock::new(&expectations);
# let mut driver = Ls7366::new_uninit(spi);
// --- snip ---
    let mdr0_configuration = Mdr0{
        quad_count_mode: QuadCountMode::Quad2x,
        filter_clock : FilterClockDivisionFactor::Two,
        index_mode: IndexMode::ClearCntr,
        cycle_count_mode: CycleCountMode::SingleCycle,
        is_index_inverted: false
    let mdr1_configuration = Mdr1{
        counter_mode: CounterMode::Byte3,
        // --- Snip ---
        # disable_counting:true,
        # flag_on_bw: false,
        # flag_on_idx: false,
        # flag_on_cmp: false,
        # flag_on_cy: false,

    driver.write_register(Target::Mdr0, &[mdr0_configuration.encode()]).unwrap();
    driver.write_register(Target::Mdr1, &[mdr1_configuration.encode()]).unwrap();