Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • master
1 result

Target

Select target project
No results found
Select Git revision
  • master
1 result
Show changes

Commits on Source 6

20 files
+ 707
165
Compare changes
  • Side-by-side
  • Inline

Files

Original line number Original line Diff line number Diff line
@@ -19,7 +19,7 @@
            "runToMain": true,
            "runToMain": true,
            "svdFile": "${workspaceRoot}/.vscode/STM32F401.svd",
            "svdFile": "${workspaceRoot}/.vscode/STM32F401.svd",
            "configFiles": [
            "configFiles": [
                "interface/stlink-v2-1.cfg",
                "interface/stlink.cfg",
                "target/stm32f4x.cfg"
                "target/stm32f4x.cfg"
            ],
            ],
            "preRestartCommands": [
            "preRestartCommands": [
@@ -44,6 +44,41 @@
            "executable": "./target/thumbv7em-none-eabihf/debug/examples/${fileBasenameNoExtension}",
            "executable": "./target/thumbv7em-none-eabihf/debug/examples/${fileBasenameNoExtension}",
            "cpu": "cortex-m4",
            "cpu": "cortex-m4",
        },
        },
        {
            "type": "cortex-debug",
            "request": "launch",
            "name": "Cortex Debug 48Mhz",
            "servertype": "openocd",
            "cwd": "${workspaceRoot}",
            "preLaunchTask": "cargo build --example",
            "runToMain": true,
            "svdFile": "${workspaceRoot}/.vscode/STM32F401.svd",
            "configFiles": [
                "interface/stlink.cfg",
                "target/stm32f4x.cfg"
            ],
            "preRestartCommands": [
                "load",
            ],
            "postLaunchCommands": [
                "monitor arm semihosting enable"
            ],
            "swoConfig": {
                "enabled": true,
                "cpuFrequency": 48000000,
                "swoFrequency": 2000000,
                "source": "probe",
                "decoders": [
                    {
                        "type": "console",
                        "label": "ITM",
                        "port": 0
                    }
                ]
            },
            "executable": "./target/thumbv7em-none-eabihf/debug/examples/${fileBasenameNoExtension}",
            "cpu": "cortex-m4",
        },
        {
        {
            "type": "cortex-debug",
            "type": "cortex-debug",
            "request": "launch",
            "request": "launch",
@@ -54,7 +89,7 @@
            "runToMain": true,
            "runToMain": true,
            "svdFile": "${workspaceRoot}/.vscode/STM32F401.svd",
            "svdFile": "${workspaceRoot}/.vscode/STM32F401.svd",
            "configFiles": [
            "configFiles": [
                "interface/stlink-v2-1.cfg",
                "interface/stlink.cfg",
                "target/stm32f4x.cfg"
                "target/stm32f4x.cfg"
            ],
            ],
            "preRestartCommands": [
            "preRestartCommands": [
@@ -78,6 +113,41 @@
            },
            },
            "executable": "./target/thumbv7em-none-eabihf/release/examples/${fileBasenameNoExtension}",
            "executable": "./target/thumbv7em-none-eabihf/release/examples/${fileBasenameNoExtension}",
            "cpu": "cortex-m4",
            "cpu": "cortex-m4",
        },
        {
            "type": "cortex-debug",
            "request": "launch",
            "name": "Cortex Release 48Mhz",
            "servertype": "openocd",
            "cwd": "${workspaceRoot}",
            "preLaunchTask": "cargo build --example --release",
            "runToMain": true,
            "svdFile": "${workspaceRoot}/.vscode/STM32F401.svd",
            "configFiles": [
                "interface/stlink.cfg",
                "target/stm32f4x.cfg"
            ],
            "preRestartCommands": [
                "load",
            ],
            "postLaunchCommands": [
                "monitor arm semihosting enable"
            ],
            "swoConfig": {
                "enabled": true,
                "cpuFrequency": 48000000,
                "swoFrequency": 2000000,
                "source": "probe",
                "decoders": [
                    {
                        "type": "console",
                        "label": "ITM",
                        "port": 0
                    }
                    }
                ]
                ]
            },
            "executable": "./target/thumbv7em-none-eabihf/release/examples/${fileBasenameNoExtension}",
            "cpu": "cortex-m4",
        }
        }
    ]
}.
 No newline at end of file
+25 −15
Original line number Original line Diff line number Diff line
# Changelog
# Changelog


## 2021-03-19

- `examples/itm_rtic_hello_48MHz.rs`, example to trace ITM, when processor runs at 48MHz, useful to debug USB applications.
  
- `.vscode/launch.json`, added 48MHz itm tracing profiles. (Now consistenly using `stlink.cfg`.)
  
## 2021-03-18

- `examples/usb-mouse.rs`, a very small example using external hid library.
  
## 2021-03-07
## 2021-03-07


- examples/rtic_bare7.rs, using embedded HAL.
- `examples/rtic_bare7.rs`, using embedded HAL.
- examples/rtic_bare8.rs, serial communication, bad design.
- `examples/rtic_bare8.rs`, serial communication, bad design.
- examples/rtic_bare9.rs, serial communication, good design.
- `examples/rtic_bare9.rs`, serial communication, good design.
  
  
## 2021-03-05
## 2021-03-05


- examples/rtic_bare6.rs, setup and validate the clock tree.
- `examples/rtic_bare6.rs`, setup and validate the clock tree.


## 2021-02-28
## 2021-02-28


- examples/rtic_bare2.rs, raw timer access.
- `examples/rtic_bare2.rs`, raw timer access.
- examples/rtic_bare3.rs, timing abstractions.
- `examples/rtic_bare3.rs`, timing abstractions.
- examples/rtic_bare4.rs, a simple bare metal peripheral access API.
- `examples/rtic_bare4.rs`, a simple bare metal peripheral access API.
- examples/rtic_bare5.rs, write your own C-like peripheral access API.
- `examples/rtic_bare5.rs`, write your own C-like peripheral access API.


## 2021-02-26
## 2021-02-26


- examples/bare1.rs, bare metal 101!
- `examples/bare1.rs`, bare metal 101!
  
  
## 2021-02-23
## 2021-02-23


- examples/rtic_blinky.rs, added instructions to terminal based debugging
- `examples/rtic_blinky.rs`, added instructions to terminal based debugging
  
  
## 2021-02-22
## 2021-02-22


- memory.x, reduced flash size to 128k to match light-weight target
- `memory.x`, reduced flash size to 128k to match light-weight target
- Cargo.toml, updated dependencies to latest stm32f4xx-hal/pac
- `Cargo.toml`, updated dependencies to latest `stm32f4xx-hal/pac`


Some experiments (wip):
Some experiments (wip):


- examples/rtt_rtic_i2c.rs, spi emulation over i2c
- `examples/rtt_rtic_i2c.rs`, spi emulation over i2c
- src/pwm3389e, driver using emulated spi
- `src/pwm3389e`, driver using emulated spi


## 2021-02-16
## 2021-02-16


- rtt_rtic_usb_mouse updated
- `rtt_rtic_usb_mouse` updated
  Notice, requires release build
  Notice, requires release build


## 2021-02-15
## 2021-02-15
+14 −21
Original line number Original line Diff line number Diff line
@@ -7,9 +7,11 @@ version = "0.1.0"


[dependencies]
[dependencies]
cortex-m = { version = "0.7.1", features = ["linker-plugin-lto"] }
cortex-m = { version = "0.7.1", features = ["linker-plugin-lto"] }
# cortex-m = { version = "0.7.1" }
cortex-m-rt = "0.6.13"
cortex-m-rt = "0.6.13"
cortex-m-semihosting = "0.3.7"
cortex-m-semihosting = "0.3.7"
cortex-m-rtic = "0.5.5"
cortex-m-rtic = "0.5.5"
# embedded-hal = { version = "0.2.4", features = ["unproven"] }
embedded-hal = "0.2.4"
embedded-hal = "0.2.4"
usb-device = "0.2.7"
usb-device = "0.2.7"


@@ -17,7 +19,7 @@ usb-device = "0.2.7"
panic-halt = "0.2.0"
panic-halt = "0.2.0"


# Uncomment for the itm panic examples.
# Uncomment for the itm panic examples.
#panic-itm = "0.4.2"
panic-itm = "0.4.2"


# Uncomment for the rtt-timing examples.
# Uncomment for the rtt-timing examples.
panic-rtt-target = { version = "0.1.1", features = ["cortex-m"] }
panic-rtt-target = { version = "0.1.1", features = ["cortex-m"] }
@@ -26,18 +28,18 @@ panic-rtt-target = { version = "0.1.1", features = ["cortex-m"] }
panic-semihosting = "0.5.6"
panic-semihosting = "0.5.6"


# Tracing
# Tracing
rtt-target = { version = "0.3.0", features = ["cortex-m"] }
rtt-target = { version = "0.3.1", features = ["cortex-m"] }
nb = "1.0.0"
usbd-hid = "0.5.0"
micromath = "1.1.0"


[dependencies.stm32f4]
[dependencies.stm32f4]
version = "0.13.0"
version = "0.13.0"
features = ["stm32f411", "rt"]
features = ["stm32f411", "rt"]


# Uncomment for the allocator example.
# alloc-cortex-m = "0.4.0"



[dependencies.stm32f4xx-hal]
[dependencies.stm32f4xx-hal]
version = "0.8.3"
version = "0.9.0"
features = ["rt", "stm32f411", "usb_fs"] 
features = ["rt", "stm32f411", "usb_fs"] 
# Enable to use the latest git version
# Enable to use the latest git version
# gitgit = "https://github.com/stm32-rs/stm32f4xx-hal"
# gitgit = "https://github.com/stm32-rs/stm32f4xx-hal"
@@ -45,28 +47,19 @@ features = ["rt", "stm32f411", "usb_fs"]
# path = "../stm32f4xx-hal"
# path = "../stm32f4xx-hal"


# this lets you use `cargo fix`!
# this lets you use `cargo fix`!
[[bin]]
# [[bin]]
name = "app"
# name = "app"
test = false
# # test = false
bench = false
# bench = false


[profile.dev]
[profile.dev]
incremental = false
incremental = false
codegen-units = 1
codegen-units = 1
overflow-checks = false  


[profile.release]
[profile.release]
incremental = false
codegen-units = 1 # better optimizations
codegen-units = 1 # better optimizations
debug = true      # symbols are nice and they don't increase the size on Flash
debug = true      # symbols are nice and they don't increase the size on Flash
lto = true        # better optimizations
lto = true        # better optimizations


# [features]
# nightly = ["cortex-m/inline-asm"]

# # this lets you use `cargo fix`!
# [[bin]]
# name = "app"
# test = false
# bench = false
+4 −4
Original line number Original line Diff line number Diff line
@@ -197,9 +197,9 @@ D+ used for re-enumeration. You don't need to connect the V+ from the USB cable,
  - If this does not work you can try to erase the flash memory (the program running on the STM32F401/F11).
  - If this does not work you can try to erase the flash memory (the program running on the STM32F401/F11).


    ``` shell
    ``` shell
    > st-util erase
    > st-flash erase
    st-flash 1.6.1
    st-flash 1.7.0
    2021-01-11T16:02:14 INFO common.c: F4xx (Dynamic Efficency): 96 KiB SRAM, 512 KiB flash in at least 16 KiB pages.
    2021-06-23T14:07:35 INFO common.c: F4xx (Dynamic Efficency): 96 KiB SRAM, 512 KiB flash in at least 16 KiB pages.
    Mass erasing.......
    Mass erasing.......
    ```
    ```


Original line number Original line Diff line number Diff line
@@ -9,6 +9,10 @@ use stm32f4;
const APP: () = {
const APP: () = {
    #[init]
    #[init]
    fn init(cx: init::Context) {
    fn init(cx: init::Context) {
        // Set up the system clock.
        let rcc = ctx.device.RCC.constrain();
        let _clocks = rcc.cfgr.sysclk(48.mhz()).require_pll48clk().freeze();

        let mut p = cx.core;
        let mut p = cx.core;
        let stim = &mut p.ITM.stim[0];
        let stim = &mut p.ITM.stim[0];
        for a in 0..=10 {
        for a in 0..=10 {
+27 −0
Original line number Original line Diff line number Diff line
// itm_rtic_hello_48Mhz
//
// Use the vscode 48Mhz launch profiles

#![no_main]
#![no_std]

use cortex_m::iprintln;
use panic_halt as _;

use stm32f4xx_hal::prelude::*;

#[rtic::app(device = stm32f4xx_hal::stm32, peripherals = true)]
const APP: () = {
    #[init]
    fn init(ctx: init::Context) {
        // Set up the system clock.
        let rcc = ctx.device.RCC.constrain();
        let _clocks = rcc.cfgr.sysclk(48.mhz()).require_pll48clk().freeze();

        let mut p = ctx.core;
        let stim = &mut p.ITM.stim[0];
        for a in 0..=10 {
            iprintln!(stim, "RTIC Hello, world!! {}", a);
        }
    }
};
Original line number Original line Diff line number Diff line
@@ -86,15 +86,15 @@ const APP: () = {
            device.SPI2,
            device.SPI2,
            (sck, miso, mosi),
            (sck, miso, mosi),
            MODE_3,
            MODE_3,
            stm32f4xx_hal::time::KiloHertz(2000).into(),
            stm32f4xx_hal::time::KiloHertz(200).into(),
            clocks,
            clocks,
        );
        );


        let mut delay = DwtDelay::new(&mut core.DWT, clocks);
        let delay = DwtDelay::new(&mut core.DWT, clocks);
        let mut pmw3389 = pmw3389::Pmw3389::new(spi, cs, delay).unwrap();
        let mut pmw3389 = pmw3389::Pmw3389::new(spi, cs, delay).unwrap();


        // set in burst mode
        // set in burst mode
        pmw3389.write_register(Register::MotionBurst, 0x00);
        pmw3389.write_register(Register::MotionBurst, 0x00).unwrap();


        // semantically, the monotonic timer is frozen at time "zero" during `init`
        // semantically, the monotonic timer is frozen at time "zero" during `init`
        // NOTE do *not* call `Instant::now` in this context; it will return a nonsense value
        // NOTE do *not* call `Instant::now` in this context; it will return a nonsense value
@@ -111,8 +111,10 @@ const APP: () = {
        static mut COUNTER: u32 = 0;
        static mut COUNTER: u32 = 0;
        static mut POS_X: i64 = 0;
        static mut POS_X: i64 = 0;


        // run each ms
        *COUNTER += 1;
        *COUNTER += 1;
        if *COUNTER == 1000 / RATIO {
        if *COUNTER == 1000 {
            // run each s
            cx.spawn.trace(*POS_X).unwrap();
            cx.spawn.trace(*POS_X).unwrap();
            *COUNTER = 0;
            *COUNTER = 0;
        }
        }
@@ -121,9 +123,7 @@ const APP: () = {
        *POS_X += x as i64;
        *POS_X += x as i64;


        // task should run each second N ms (16_000 cycles at 16MHz)
        // task should run each second N ms (16_000 cycles at 16MHz)
        cx.schedule
        cx.schedule.poll(cx.scheduled + 16_000.cycles()).unwrap();
            .poll(cx.scheduled + (RATIO * 16_000).cycles())
            .unwrap();
    }
    }


    #[task(priority = 1)]
    #[task(priority = 1)]
Original line number Original line Diff line number Diff line
@@ -9,6 +9,7 @@
#![no_main]
#![no_main]
#![no_std]
#![no_std]


use cortex_m_semihosting::hprintln;
use panic_semihosting as _;
use panic_semihosting as _;
use stm32f4;
use stm32f4;


@@ -18,6 +19,7 @@ const APP: () = {
    #[inline(never)] // avoid inlining of this function/task
    #[inline(never)] // avoid inlining of this function/task
    #[no_mangle] // to strip hash from symbols (easier to read)
    #[no_mangle] // to strip hash from symbols (easier to read)
    fn init(_cx: init::Context) {
    fn init(_cx: init::Context) {
        hprintln!("hello");
        let mut x = core::u32::MAX - 1;
        let mut x = core::u32::MAX - 1;
        loop {
        loop {
            // cortex_m::asm::bkpt();
            // cortex_m::asm::bkpt();
Original line number Original line Diff line number Diff line
@@ -17,7 +17,7 @@ use stm32f4xx_hal::{
    gpio::{gpioa::PA5, Output, PushPull},
    gpio::{gpioa::PA5, Output, PushPull},
    prelude::*,
    prelude::*,
};
};
;

use embedded_hal::digital::v2::{OutputPin, ToggleableOutputPin};
use embedded_hal::digital::v2::{OutputPin, ToggleableOutputPin};


const OFFSET: u32 = 8_000_000;
const OFFSET: u32 = 8_000_000;
+315 −0
Original line number Original line Diff line number Diff line
//! examples/rtt-pwm-sine.rs
//! cargo run --examples rtt-pwm-sine --release

// #![deny(unsafe_code)]
// #![deny(warnings)]
#![no_main]
#![no_std]

use cortex_m::{asm, peripheral::DWT};

use panic_rtt_target as _;
use rtic::cyccnt::{Instant, U32Ext as _};
use rtt_target::{rprint, rprintln, rtt_init_print};

use core::f32::consts::PI;
use micromath::F32Ext;

use stm32f4xx_hal::{
    bb,
    dwt::Dwt,
    gpio::Speed,
    gpio::{
        gpiob::{PB10, PB4},
        gpioc::{PC2, PC3},
        Alternate, Output, PushPull,
    },
    prelude::*,
    pwm,
    rcc::Clocks,
    spi::Spi,
    stm32,
};

use embedded_hal::spi::MODE_3;
use panic_rtt_target as _;

use app::{
    pmw3389::{self, Register},
    DwtDelay,
};

type PMW3389T = pmw3389::Pmw3389<
    Spi<
        stm32f4xx_hal::stm32::SPI2,
        (
            PB10<Alternate<stm32f4xx_hal::gpio::AF5>>,
            PC2<Alternate<stm32f4xx_hal::gpio::AF5>>,
            PC3<Alternate<stm32f4xx_hal::gpio::AF5>>,
        ),
    >,
    PB4<Output<PushPull>>,
>;

include!(concat!(env!("OUT_DIR"), "/sin_abs_const.rs"));

#[rtic::app(device = stm32f4xx_hal::stm32,  monotonic = rtic::cyccnt::CYCCNT, peripherals = true)]
const APP: () = {
    struct Resources {
        // late resources
        TIM1: stm32::TIM1,
        pmw3389: PMW3389T,
    }
    #[init(schedule = [pwm_out, poll])]
    fn init(mut cx: init::Context) -> init::LateResources {
        rtt_init_print!();
        rprintln!("init");

        let device = cx.device;
        let mut core = cx.core;

        // Initialize (enable) the monotonic timer (CYCCNT)
        core.DCB.enable_trace();
        core.DWT.enable_cycle_counter();

        let rcc = device.RCC.constrain();
        // Set up the system clock. 96 MHz?
        let clocks = rcc.cfgr.sysclk(96.mhz()).pclk1(24.mhz()).freeze();

        // Configure SPI
        // spi2
        // sck    - pb10, (yellow)
        // miso   - pc2, (red)
        // mosi   - pc3, (orange)
        // ncs    - pb4, (long yellow)
        // motion - (brown)
        //
        // +5, (white)
        // gnd, (black)

        cortex_m::asm::dsb(); // chip errata
        let gpiob = device.GPIOB.split();
        cortex_m::asm::dsb(); // chip errata
        let gpioc = device.GPIOC.split();
        cortex_m::asm::dsb(); // chip errata

        let sck = gpiob.pb10.into_alternate_af5().set_speed(Speed::VeryHigh);
        let miso = gpioc.pc2.into_alternate_af5().set_speed(Speed::High);
        let mosi = gpioc.pc3.into_alternate_af5().set_speed(Speed::High);
        let cs = gpiob.pb4.into_push_pull_output().set_speed(Speed::High);

        let spi = Spi::spi2(
            device.SPI2,
            (sck, miso, mosi),
            MODE_3,
            stm32f4xx_hal::time::KiloHertz(2000).into(),
            clocks,
        );

        let delay = DwtDelay::new(&mut core.DWT, clocks);
        let mut pmw3389 = pmw3389::Pmw3389::new(spi, cs, delay).unwrap();

        // // set in burst mode
        // pmw3389.write_register(Register::MotionBurst, 0x00).unwrap();

        // setup TIM1 as PWM (for implementing an 8 bit DA)
        let gpioa = device.GPIOA.split();
        cortex_m::asm::dsb(); // chip errata

        // we set the pins to VeryHigh to get the sharpest waveform possible
        // (rise and fall times should have similar characteristics)
        let _channels = (
            gpioa.pa8.into_alternate_af1().set_speed(Speed::VeryHigh),
            gpioa.pa9.into_alternate_af1().set_speed(Speed::VeryHigh),
        );

        // Setup PWM RAW
        let tim1 = device.TIM1;
        // Here we need unsafe as we are "stealing" the RCC peripheral
        // At this point it has been contrained into SysConf and used to set clocks
        let rcc = unsafe { &(*stm32::RCC::ptr()) };

        rcc.apb2enr.modify(|_, w| w.tim1en().set_bit());
        rcc.apb2rstr.modify(|_, w| w.tim1rst().set_bit());
        rcc.apb2rstr.modify(|_, w| w.tim1rst().clear_bit());

        // Setup chanel 1 and 2 as pwm_mode1
        tim1.ccmr1_output()
            .modify(|_, w| w.oc1pe().set_bit().oc1m().pwm_mode1());

        tim1.ccmr1_output()
            .modify(|_, w| w.oc2pe().set_bit().oc2m().pwm_mode1());

        // The reference manual is a bit ambiguous about when enabling this bit is really
        // necessary, but since we MUST enable the pre-load for the output channels then we
        // might as well enable for the auto-reload too
        tim1.cr1.modify(|_, w| w.arpe().set_bit());

        let clk = clocks.pclk2().0 * if clocks.ppre2() == 1 { 1 } else { 2 };
        // check the actual clock setup
        rprintln!("clk {}", clk);

        // we want maximum performance, thus we set the prescaler to 0
        let pre = 0;
        rprintln!("pre {}", pre);
        tim1.psc.write(|w| w.psc().bits(pre));

        // we want 8 bits of resolution
        // so our ARR = 2^8 - 1 = 256 - 1 = 255
        let arr = 255;
        rprintln!("arr {}", arr);
        tim1.arr.write(|w| unsafe { w.bits(arr) });

        //  Trigger update event to load the registers
        tim1.cr1.modify(|_, w| w.urs().set_bit());
        tim1.egr.write(|w| w.ug().set_bit());
        tim1.cr1.modify(|_, w| w.urs().clear_bit());

        // Set main output enable of all Output Compare (OC) registers
        tim1.bdtr.modify(|_, w| w.moe().set_bit());

        // Set output enable for channels 1 and 2
        tim1.ccer.write(|w| w.cc1e().set_bit().cc2e().set_bit());

        // Setup the timer
        tim1.cr1.write(|w| {
            w.cms()
                .bits(0b00) // edge aligned mode
                .dir() // counter used as up-counter
                .clear_bit()
                .opm() // one pulse mode
                .clear_bit()
                .cen() // enable counter
                .set_bit()
        });

        // Set main output enable of all Output Compare (OC) registers
        tim1.bdtr.modify(|_, w| w.moe().set_bit());

        // Set duty cycle of Channels
        tim1.ccr1.write(|w| unsafe { w.ccr().bits(128) });
        tim1.ccr2.write(|w| unsafe { w.ccr().bits(128) });

        // Set preload for the CCx
        tim1.cr2.write(|w| w.ccpc().set_bit());

        // Enable update events
        tim1.dier.write(|w| w.uie().enabled());
        tim1.sr.modify(|_, w| w.uif().clear());

        // just to check that we actually get update events
        while tim1.sr.read().uif().is_clear() {
            rprint!("-");
        }
        rprintln!("here");
        tim1.sr.modify(|_, w| w.uif().clear());

        cx.schedule.pwm_out(cx.start + PWM_CYCLES.cycles()).ok();
        cx.schedule.poll(cx.start + POLL_CYCLES.cycles()).ok();
        // pass on late resources
        init::LateResources {
            TIM1: tim1,
            pmw3389,
        }
    }

    #[idle]
    fn idle(_cx: idle::Context) -> ! {
        rprintln!("idle");
        // panic!("panic");
        loop {
            asm::nop()
        }
    }

    #[task(priority = 1)]
    fn trace(_cx: trace::Context, pos_x: i64, pos_y: i64) {
        static mut OLD_POS_X: i64 = 0;
        static mut OLD_POS_Y: i64 = 0;
        rprintln!(
            "@{:?}, pos_x {:010}, diff {:010}, pos_y {:010}, diff {:010} ",
            Instant::now(),
            pos_x,
            pos_x.wrapping_sub(*OLD_POS_X),
            pos_y,
            pos_y.wrapping_sub(*OLD_POS_Y),
        );
        *OLD_POS_X = pos_x;
        *OLD_POS_Y = pos_y;
    }

    #[task(priority = 2, resources = [pmw3389], schedule = [poll], spawn = [trace])]
    fn poll(cx: poll::Context) {
        static mut COUNTER: u32 = 0;
        static mut POS_X: i64 = 0;
        static mut POS_Y: i64 = 0;

        // run each ms
        *COUNTER += 1;
        if *COUNTER == 1000 {
            // run each s
            cx.spawn.trace(*POS_X, *POS_Y).unwrap();
            *COUNTER = 0;
        }

        let pmw3389 = cx.resources.pmw3389;

        //write 0x01 to Motion register and read from it to freeze the motion values and make them available
        pmw3389.write_register(Register::Motion, 0x01).unwrap();
        let _ = pmw3389.read_register(Register::Motion).unwrap();

        let xl: u8 = pmw3389.read_register(Register::DeltaXL).unwrap();
        let xh: u8 = pmw3389.read_register(Register::DeltaXH).unwrap();
        let yl = pmw3389.read_register(Register::DeltaYL).unwrap();
        let yh = pmw3389.read_register(Register::DeltaYH).unwrap();

        // let (x, _y) = cx.resources.pmw3389.read_status().unwrap();
        *POS_X += (((xl as u16) | ((xh as u16) << 8)) as i16) as i64;
        *POS_Y += (((yl as u16) | ((yh as u16) << 8)) as i16) as i64;

        // task should run each second N ms (96_000 cycles at 96MHz)
        cx.schedule
            .poll(cx.scheduled + POLL_CYCLES.cycles())
            .unwrap();
    }

    #[task(priority = 3, resources = [TIM1], schedule = [pwm_out])]
    fn pwm_out(cx: pwm_out::Context) {
        static mut INDEX: u16 = 0;
        static mut LEFT: u16 = 0;
        static mut RIGHT: u16 = 0;
        // static mut FLOAT: u16 = 0;

        let tim1 = cx.resources.TIM1;

        tim1.ccr1.write(|w| unsafe { w.ccr().bits(*LEFT) });
        tim1.ccr2.write(|w| unsafe { w.ccr().bits(*RIGHT) });
        // tim1.ccr2.write(|w| unsafe { w.ccr().bits(*FLOAT) });

        cx.schedule
            .pwm_out(cx.scheduled + PWM_CYCLES.cycles())
            .unwrap();

        *INDEX = (*INDEX).wrapping_add(1_000);
        // let f: f32 = (*INDEX as f32 * 2.0 * PI) / 65536.0;
        // *FLOAT = (128.0 + f.sin() * 128.0) as u16;

        *LEFT = SINE_BUF[*INDEX as usize] as u16;
        *RIGHT = SINE_BUF[*INDEX as usize] as u16;

        // if cx.scheduled.elapsed() > 1500.cycles() {
        //     panic!("task overrun");
        // }
    }

    extern "C" {
        fn EXTI0();
        fn EXTI1();
        fn EXTI2();
    }
};

// We aim for a sampling rate of 48kHz, assuming that the input filter of the
// sound card used to sample the generated signal has an appropriate input filter
const PWM_CYCLES: u32 = 2000; // 96_000_000 / 2_000 = 48_000 Hz
const POLL_CYCLES: u32 = 96_000; // 96_000_000 / 96_000 = 1_000 Hz
Original line number Original line Diff line number Diff line
@@ -6,14 +6,17 @@
#![no_main]
#![no_main]
#![no_std]
#![no_std]


use core::f32::consts::PI;
// use core::f32::consts::PI;
use cortex_m::{asm, peripheral::DWT};
use cortex_m::{asm, peripheral::DWT};
// use panic_halt as _;
// use panic_halt as _;
use panic_rtt_target as _;
use panic_rtt_target as _;
use rtic::cyccnt::{Instant, U32Ext as _};
use rtic::cyccnt::{Instant, U32Ext as _};
use rtt_target::{rprint, rprintln, rtt_init_print};
use rtt_target::{rprint, rprintln, rtt_init_print};


use stm32f4xx_hal::{bb, dma, gpio::Speed, prelude::*, pwm, stm32};
use core::f32::consts::PI;
use micromath::F32Ext;

use stm32f4xx_hal::{bb, gpio::Speed, prelude::*, pwm, stm32};


include!(concat!(env!("OUT_DIR"), "/sin_abs_const.rs"));
include!(concat!(env!("OUT_DIR"), "/sin_abs_const.rs"));


@@ -153,19 +156,23 @@ const APP: () = {
        static mut INDEX: u16 = 0;
        static mut INDEX: u16 = 0;
        static mut LEFT: u16 = 0;
        static mut LEFT: u16 = 0;
        static mut RIGHT: u16 = 0;
        static mut RIGHT: u16 = 0;
        static mut FLOAT: u16 = 0;


        let tim1 = cx.resources.TIM1;
        let tim1 = cx.resources.TIM1;


        tim1.ccr1.write(|w| unsafe { w.ccr().bits(*LEFT) });
        tim1.ccr1.write(|w| unsafe { w.ccr().bits(*LEFT) });
        tim1.ccr2.write(|w| unsafe { w.ccr().bits(*RIGHT) });
        // tim1.ccr2.write(|w| unsafe { w.ccr().bits(*RIGHT) });
        tim1.ccr2.write(|w| unsafe { w.ccr().bits(*FLOAT) });


        *INDEX = (*INDEX).wrapping_add(10_000);
        *INDEX = (*INDEX).wrapping_add(10_000);
        let f: f32 = (*INDEX as f32 * 2.0 * PI) / 65536.0;
        *FLOAT = (128.0 + f.sin() * 128.0) as u16;
        cx.schedule.pwm_out(cx.scheduled + PERIOD.cycles()).ok();
        cx.schedule.pwm_out(cx.scheduled + PERIOD.cycles()).ok();


        *LEFT = SINE_BUF[*INDEX as usize] as u16;
        *LEFT = SINE_BUF[*INDEX as usize] as u16;
        *RIGHT = SINE_BUF[*INDEX as usize] as u16;
        *RIGHT = SINE_BUF[*INDEX as usize] as u16;


        if cx.scheduled.elapsed() > 300.cycles() {
        if cx.scheduled.elapsed() > 500.cycles() {
            panic!("task overrun");
            panic!("task overrun");
        }
        }
    }
    }
Original line number Original line Diff line number Diff line
@@ -47,7 +47,7 @@ const APP: () = {
        // Setup PWM RAW
        // Setup PWM RAW
        let tim1 = dp.TIM1;
        let tim1 = dp.TIM1;
        // Here we need unsafe as we are "stealing" the RCC peripheral
        // Here we need unsafe as we are "stealing" the RCC peripheral
        // At this point it has been contrained into SysConf and used to set clocks
        // At this point it has been constrained into SysConf and used to set clocks
        let rcc = unsafe { &(*stm32::RCC::ptr()) };
        let rcc = unsafe { &(*stm32::RCC::ptr()) };


        rcc.apb2enr.modify(|_, w| w.tim1en().set_bit());
        rcc.apb2enr.modify(|_, w| w.tim1en().set_bit());
Original line number Original line Diff line number Diff line
//! examples/rtt_timing.rs
//! examples/rtt_timing.rs
//! cargo run --examples rtt-timing
//! cargo run --examples rtt-timing


#![deny(unsafe_code)]
#![deny(warnings)]
#![deny(warnings)]
#![no_main]
#![no_main]
#![no_std]
#![no_std]
Original line number Original line Diff line number Diff line
@@ -6,7 +6,6 @@
#![no_std]
#![no_std]


use cortex_m::{asm::delay, delay};
use cortex_m::{asm::delay, delay};
// use panic_halt as _;
use panic_rtt_target as _;
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use rtt_target::{rprintln, rtt_init_print};


@@ -21,15 +20,36 @@ use stm32f4xx_hal::{
    stm32::I2C1,
    stm32::I2C1,
};
};


use rtic::cyccnt::{Instant, U32Ext as _};

use app::{
use app::{
    pmw3389e::{self, Register},
    pmw3389e::{self, Register},
    DwtDelay,
    DwtDelay,
};
};


#[rtic::app(device = stm32f4xx_hal::stm32, peripherals = true)]
const OFFSET: u32 = 8_000_000 / 10;
const LOG_OFFSET: u32 = 8_000_000;

#[rtic::app(device = stm32f4xx_hal::stm32, monotonic = rtic::cyccnt::CYCCNT, peripherals = true)]
const APP: () = {
const APP: () = {
    #[init]
    struct Resources {
    fn init(cx: init::Context) {
        pmw3389: pmw3389e::Pmw3389e<
            SC18IS602::SH18IS602<
                I2c<
                    I2C1,
                    (
                        PB8<AlternateOD<stm32f4xx_hal::gpio::AF4>>,
                        PB9<AlternateOD<stm32f4xx_hal::gpio::AF4>>,
                    ),
                >,
            >,
            SC18IS602::Error,
        >,
        #[init((0, 0))]
        pos: (i64, i64),
    }
    #[init(schedule = [poll, log])]
    fn init(cx: init::Context) -> init::LateResources {
        rtt_init_print!();
        rtt_init_print!();
        rprintln!("init");
        rprintln!("init");
        let dp = cx.device;
        let dp = cx.device;
@@ -41,6 +61,7 @@ const APP: () = {


        // Initialize (enable) the monotonic timer (CYCCNT)
        // Initialize (enable) the monotonic timer (CYCCNT)
        cp.DCB.enable_trace();
        cp.DCB.enable_trace();
        cp.DWT.enable_cycle_counter();


        // Set up I2C.
        // Set up I2C.
        let gpiob = dp.GPIOB.split();
        let gpiob = dp.GPIOB.split();
@@ -52,54 +73,17 @@ const APP: () = {


        use embedded_hal::spi::MODE_3;
        use embedded_hal::spi::MODE_3;
        use SC18IS602::{Order, Speed, SH18IS602};
        use SC18IS602::{Order, Speed, SH18IS602};
        let mut spi_emu =
        let spi_emu = SH18IS602::new(i2c, 0, Order::MsbFirst, MODE_3, Speed::Speed1843kHz, true);
            SH18IS602::new(i2c, 0, Order::MsbFirst, MODE_3, Speed::Speed1843kHz, true);


        rprintln!("spi_emu initialized");
        rprintln!("spi_emu initialized");


        // reset SPI transfer
        spi_emu.set_low().ok();
        cortex_m::asm::delay(1_000_000);
        spi_emu.set_high().ok();
        cortex_m::asm::delay(1_000_000);

        rprintln!("set to gpio management");

        // try split transaction
        rprintln!("try split transaction");
        // the write part
        spi_emu.set_low().unwrap();
        let mut req = [0x00];
        spi_emu.transfer(&mut req).unwrap();
        rprintln!("id request {:02x?}", req);

        cortex_m::asm::delay(1_000);
        // the read part
        let mut req = [00];
        spi_emu.transfer(&mut req).unwrap();
        rprintln!("id resp {:02x?}", req);

        spi_emu.set_high().unwrap();

        rprintln!("try split transaction");
        // the write part
        spi_emu.set_low().unwrap();
        let mut req = [0x01];
        spi_emu.transfer(&mut req).unwrap();
        rprintln!("version request {:02x?}", req);

        cortex_m::asm::delay(1_000);
        // the read part
        let mut req = [00];
        spi_emu.transfer(&mut req).unwrap();
        rprintln!("version resp {:02x?}", req);

        spi_emu.set_high().unwrap();

        let delay = DwtDelay::new(&mut cp.DWT, clocks);
        let delay = DwtDelay::new(&mut cp.DWT, clocks);
        let pmw3389 = pmw3389e::Pmw3389e::new(spi_emu, delay).unwrap();
        let pmw3389 = pmw3389e::Pmw3389e::new(spi_emu, delay).unwrap();


        rprintln!("success");
        rprintln!("success");
        cx.schedule.poll(cx.start + OFFSET.cycles()).unwrap();
        cx.schedule.log(cx.start + LOG_OFFSET.cycles()).unwrap();
        init::LateResources { pmw3389 }
    }
    }


    #[idle]
    #[idle]
@@ -109,6 +93,52 @@ const APP: () = {
            continue;
            continue;
        }
        }
    }
    }

    #[task(priority = 2, resources = [pmw3389, pos], schedule = [poll])]
    fn poll(cx: poll::Context) {
        // rprintln!("poll  @ {:?}", Instant::now());

        // static mut X: i64 = 0;
        // static mut Y: i64 = 0;

        cx.schedule.poll(cx.scheduled + OFFSET.cycles()).unwrap();
        let pmw3389 = cx.resources.pmw3389;

        pmw3389.write_register(Register::Motion, 0x01).unwrap();

        let motion = pmw3389.read_register(Register::Motion).unwrap();
        let xl = pmw3389.read_register(Register::DeltaXL).unwrap();
        let xh = pmw3389.read_register(Register::DeltaXH).unwrap();
        let yl = pmw3389.read_register(Register::DeltaYL).unwrap();
        let yh = pmw3389.read_register(Register::DeltaYH).unwrap();

        let x = (xl as u16 + (xh as u16) << 8) as i16;
        let y = (yl as u16 + (yh as u16) << 8) as i16;

        cx.resources.pos.0 += x as i64;
        cx.resources.pos.1 += y as i64;

        // let surface = motion & 0x08;
        // let motion_detect = motion & 0x80;

        // rprintln!(
        //     "motion {}, surface {}, (x, y) {:?}",
        //     motion_detect,
        //     surface,
        //     (x, y),
        // );
    }

    #[task(priority = 1, resources = [pos], schedule = [log])]
    fn log(mut cx: log::Context) {
        cx.schedule.log(cx.scheduled + LOG_OFFSET.cycles()).unwrap();
        cx.resources.pos.lock(|pos| rprintln!("(x, y) {:?}", pos));
    }

    extern "C" {
        fn EXTI0();
        fn EXTI1();
    }
};
};


// SC18IS602
// SC18IS602
@@ -222,8 +252,12 @@ mod SC18IS602 {
                | (mode.phase as u8) << 2
                | (mode.phase as u8) << 2
                | speed as u8;
                | speed as u8;


            rprintln!("configuring i2c->spi bridge");

            device.i2c.write(addr, &mut [SpiConfigure.id(), cfg]).ok();
            device.i2c.write(addr, &mut [SpiConfigure.id(), cfg]).ok();


            rprintln!("spi bridge configured");

            if gpio {
            if gpio {
                device.set_ss0_gpio();
                device.set_ss0_gpio();
            } else {
            } else {
@@ -258,8 +292,6 @@ mod SC18IS602 {
        }
        }
    }
    }


    // impl<I2C> Default for SH18IS602<I2C> where I2C: i2c::Write + i2c::Read {}

    impl<I2C> Transfer<u8> for SH18IS602<I2C>
    impl<I2C> Transfer<u8> for SH18IS602<I2C>
    where
    where
        I2C: i2c::Write + i2c::Read,
        I2C: i2c::Write + i2c::Read,
@@ -290,12 +322,10 @@ mod SC18IS602 {


            // A short delay is needed
            // A short delay is needed
            // For improved performance use write if result is not needed
            // For improved performance use write if result is not needed
            cortex_m::asm::delay(1000);
            cortex_m::asm::delay(1_000);


            self.i2c.read(self.addr, words).map_err(|_| panic!()).ok();
            self.i2c.read(self.addr, words).map_err(|_| panic!()).ok();


            // rprintln!("transfer_read {:02x?}", words);

            Ok(words)
            Ok(words)
        }
        }
    }
    }
@@ -310,12 +340,13 @@ mod SC18IS602 {
            if !self.gpio {
            if !self.gpio {
                Err(Error::NotConfigured)
                Err(Error::NotConfigured)
            } else {
            } else {
                rprintln!("set low");
                // rprintln!("set low");
                //  cortex_m::asm::delay(10_000);
                self.i2c
                self.i2c
                    .write(self.addr, &[Function::GpioWrite.id(), 0x0])
                    .write(self.addr, &[Function::GpioWrite.id(), 0x0])
                    .map_err(|_| panic!())
                    .map_err(|_| panic!())
                    .ok();
                    .ok();
                cortex_m::asm::delay(100_000);
                // cortex_m::asm::delay(20_000);
                Ok(())
                Ok(())
            }
            }
        }
        }
@@ -324,7 +355,8 @@ mod SC18IS602 {
            if !self.gpio {
            if !self.gpio {
                Err(Error::NotConfigured)
                Err(Error::NotConfigured)
            } else {
            } else {
                rprintln!("set_high");
                // rprintln!("set_high");
                // cortex_m::asm::delay(10_000);
                self.i2c
                self.i2c
                    .write(self.addr, &[Function::GpioWrite.id(), 0x1])
                    .write(self.addr, &[Function::GpioWrite.id(), 0x1])
                    .map_err(|_| panic!())
                    .map_err(|_| panic!())
Original line number Original line Diff line number Diff line
@@ -324,6 +324,7 @@ fn usb_poll<B: bus::UsbBus>(
    usb_dev: &mut UsbDevice<'static, B>,
    usb_dev: &mut UsbDevice<'static, B>,
    hid: &mut HIDClass<'static, B>,
    hid: &mut HIDClass<'static, B>,
) {
) {
    // 
    if !usb_dev.poll(&mut [hid]) {
    if !usb_dev.poll(&mut [hid]) {
        return;
        return;
    }
    }

examples/usb-mouse.rs

0 → 100644
+119 −0
Original line number Original line Diff line number Diff line
// > cargo run usb-mouse
// or
// > cargo run usb-mouse --release

#![no_main]
#![no_std]

use stm32f4xx_hal::{
    gpio::{gpioc::PC13, Input, PullUp},
    otg_fs::{UsbBus, UsbBusType, USB},
    prelude::*,
    rcc::Clocks,
};
use usb_device::{bus::UsbBusAllocator, prelude::*};
use usbd_hid::{
    descriptor::{generator_prelude::*, MouseReport},
    hid_class::HIDClass,
};

use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};

#[rtic::app(device = stm32f4xx_hal::stm32, peripherals = true)]
const APP: () = {
    struct Resources {
        btn: PC13<Input<PullUp>>,
        hid: HIDClass<'static, UsbBusType>,
        usb_dev: UsbDevice<'static, UsbBus<USB>>,
    }

    #[init]
    fn init(ctx: init::Context) -> init::LateResources {
        static mut EP_MEMORY: [u32; 1024] = [0; 1024];
        static mut USB_BUS: Option<UsbBusAllocator<UsbBusType>> = None;

        rtt_init_print!();
        rprintln!("init");

        // Set up the system clock.
        let rcc = ctx.device.RCC.constrain();
        let clocks: Clocks = rcc.cfgr.sysclk(48.mhz()).require_pll48clk().freeze();
        let hclk = clocks.hclk();

        let gpioc = ctx.device.GPIOC.split();
        let btn = gpioc.pc13.into_pull_up_input();

        let gpioa = ctx.device.GPIOA.split();
        let usb = USB {
            usb_global: ctx.device.OTG_FS_GLOBAL,
            usb_device: ctx.device.OTG_FS_DEVICE,
            usb_pwrclk: ctx.device.OTG_FS_PWRCLK,
            pin_dm: gpioa.pa11.into_alternate_af10(),
            pin_dp: gpioa.pa12.into_alternate_af10(),
            hclk,
        };
        USB_BUS.replace(UsbBus::new(usb, EP_MEMORY));

        let hid = HIDClass::new(USB_BUS.as_ref().unwrap(), MouseReport::desc(), 1);
        let usb_dev = UsbDeviceBuilder::new(USB_BUS.as_ref().unwrap(), UsbVidPid(0xc410, 0x0000))
            .manufacturer("E70011E")
            .product("Mouse")
            .serial_number("1.0")
            .device_class(0)
            .build();

        init::LateResources { btn, hid, usb_dev }
    }

    #[task(binds=OTG_FS, resources = [btn, hid, usb_dev])]
    fn on_usb(ctx: on_usb::Context) {
        static mut COUNTER: u16 = 0;
        static mut FIRST: bool = true;

        if *FIRST {
            rprintln!("on_usb");
            *FIRST = false;
        }

        // destruct the context
        let (btn, usb_dev, hid) = (ctx.resources.btn, ctx.resources.usb_dev, ctx.resources.hid);

        let report = MouseReport {
            x: match *COUNTER {
                // reached after 100ms
                100 => {
                    rprintln!("10");
                    10
                }
                // reached after 199ms
                199 => {
                    rprintln!("-10");
                    -10
                }
                _ => 0,
            },
            y: 0,
            buttons: btn.is_low().unwrap().into(), // (into takes a bool into an integer)
            wheel: 0,
        };
        // wraps around after 200ms
        *COUNTER = (*COUNTER + 1) % 200;

        // push the report
        hid.push_input(&report).ok();

        // update the usb device state
        if usb_dev.poll(&mut [hid]) {
            return;
        }
    }

    #[idle]
    fn idle(_cx: idle::Context) -> ! {
        rprintln!("idle");
        loop {
            cortex_m::asm::nop();
        }
    }
};
+1 −1
Original line number Original line Diff line number Diff line
@@ -24,7 +24,7 @@ monitor arm semihosting enable
# # send captured ITM to the file itm.fifo
# # send captured ITM to the file itm.fifo
# # (the microcontroller SWO pin must be connected to the programmer SWO pin)
# # (the microcontroller SWO pin must be connected to the programmer SWO pin)
# # 8000000 must match the core clock frequency
# # 8000000 must match the core clock frequency
monitor tpiu config internal itm.txt uart off 16000000
monitor tpiu config internal itm.txt uart off 48000000


# # OR: make the microcontroller SWO pin output compatible with UART (8N1)
# # OR: make the microcontroller SWO pin output compatible with UART (8N1)
# # 8000000 must match the core clock frequency
# # 8000000 must match the core clock frequency

src/main.rs

deleted100644 → 0
+0 −20
Original line number Original line Diff line number Diff line
#![no_std]
#![no_main]

// pick a panicking behavior
use panic_halt as _; // you can put a breakpoint on `rust_begin_unwind` to catch panics
// use panic_abort as _; // requires nightly
// use panic_itm as _; // logs messages over ITM; requires ITM support
// use panic_semihosting as _; // logs messages to the host stderr; requires a debugger

use cortex_m::asm;
use cortex_m_rt::entry;

#[entry]
fn main() -> ! {
    asm::nop(); // To not have main optimize to abort in release mode, remove when you add code

    loop {
        // your code goes here
    }
}
+3 −20
Original line number Original line Diff line number Diff line
@@ -6,7 +6,7 @@ use crate::DwtDelay;
use embedded_hal::blocking::spi::{Transfer, Write};
use embedded_hal::blocking::spi::{Transfer, Write};
use embedded_hal::digital::v2::OutputPin;
use embedded_hal::digital::v2::OutputPin;


use rtt_target::{rprint, rprintln};
use rtt_target::rprintln;


#[allow(dead_code)]
#[allow(dead_code)]
#[derive(Clone, Copy)]
#[derive(Clone, Copy)]
@@ -116,23 +116,6 @@ where


        rprintln!("reset");
        rprintln!("reset");


        // shutdown

        // adns_write_reg(Shutdown, 0xb6); // Shutdown first
        // delay(300);

        // adns_com_begin(); // drop and raise ncs to reset spi port
        // delayMicroseconds(40);
        // adns_com_end();
        // delayMicroseconds(40);

        // pmw3389.write_register(Register::Shutdown, 0xb6)?;
        // pmw3389.delay.delay_ms(300);
        // pmw3389.com_begin();
        // pmw3389.delay.delay_us(40);
        // pmw3389.com_end();
        // pmw3389.delay.delay_us(40);

        // force reset
        // force reset
        pmw3389.write_register(Register::PowerUpReset, 0x5a)?;
        pmw3389.write_register(Register::PowerUpReset, 0x5a)?;


@@ -220,7 +203,7 @@ where
    }
    }


    /// Read status
    /// Read status
    pub fn read_status(&mut self) -> Result<((i16, i16)), E> {
    pub fn read_status(&mut self) -> Result<(i16, i16), E> {
        self.com_begin();
        self.com_begin();


        self.spi.transfer(&mut [Register::MotionBurst.addr()])?;
        self.spi.transfer(&mut [Register::MotionBurst.addr()])?;
@@ -340,7 +323,7 @@ where
        // // set initial CPI resolution
        // // set initial CPI resolution
        // // adns_write_reg(Config1, 0x15);
        // // adns_write_reg(Config1, 0x15);


        let cpi: u16 = 16000;
        let cpi: u16 = 1600;
        self.write_register(Register::ResolutionL, cpi as u8)?;
        self.write_register(Register::ResolutionL, cpi as u8)?;
        self.write_register(Register::ResolutionH, (cpi >> 8) as u8)?;
        self.write_register(Register::ResolutionH, (cpi >> 8) as u8)?;


+8 −8
Original line number Original line Diff line number Diff line
@@ -146,16 +146,16 @@ where


        pmw3389.upload_firmware()?;
        pmw3389.upload_firmware()?;


        // pmw3389.delay.delay_ms(1000);
        pmw3389.delay.delay_ms(1000);


        // rprintln!("Optical Chip Initialized");
        rprintln!("Optical Chip Initialized");


        // // read product id
        // read product id
        // let id = pmw3389.product_id()?;
        let id = pmw3389.product_id()?;
        // rprintln!("product_id 0x{:x}", id);
        rprintln!("product_id 0x{:x}", id);


        // let srom_id = pmw3389.read_register(Register::SROMId)?;
        let srom_id = pmw3389.read_register(Register::SROMId)?;
        // rprintln!("srom_id {}, 0x{:x}", srom_id, srom_id);
        rprintln!("srom_id {}, 0x{:x}", srom_id, srom_id);


        // // loop {
        // // loop {
        // //     pmw3389.write_register(Register::Motion, 0x01)?;
        // //     pmw3389.write_register(Register::Motion, 0x01)?;
@@ -384,7 +384,7 @@ where
        // // adns_write_reg(Config1, 0x15);
        // // adns_write_reg(Config1, 0x15);


        //            self.write_register(Register::ResolutionL, 0x15)?;
        //            self.write_register(Register::ResolutionL, 0x15)?;
        self.write_register(Register::ResolutionL, 0x5)?;
        self.write_register(Register::ResolutionL, 0x15)?;
        // self.write_register(Register::ResolutionH, 0x15)?;
        // self.write_register(Register::ResolutionH, 0x15)?;
        self.write_register(Register::ResolutionH, 0x00)?;
        self.write_register(Register::ResolutionH, 0x00)?;