How to toggle the ncs pin assigned to a slave in the DeviceTree.

Dear Support Team,

I'm trying to develop a mouse using Pixart's PAW3395 sensor. I've written functions for reading and writing data through the SPI interface. I took help from the bme280 example provided by Zephyr and the Nordic Dev Academy. The overlay remains approximately the same; however, because the power-up sequence of PAW3395 needs us to manually control the "cs" pin thus, I had to assign the cs to 2 nodes: one for the spi (spi1) and the led node (led4). Is there a better way to control the cs pin?

This is the overlay file:

/* STEP 2.1 - Create an overlay file for your board */
&i2c0 {	status = "disabled";};
&spi0 {	status = "disabled";};
&i2c1 {	status = "disabled";};

&spi1 {
    compatible = "nordic,nrf-spim";
    status = "okay";
    pinctrl-0 = <&spi1_default>;
    pinctrl-1 = <&spi1_sleep>;
    pinctrl-names = "default","sleep";
    cs-gpios = <&gpio0 30 GPIO_ACTIVE_LOW>;
    bme280: bme280@0{
        compatible = "bosch,bme280";
        reg = <0>;
        spi-max-frequency = <125000>;
    };
};
/* STEP 2.2 - Change the pin configuration */

&pinctrl {
    spi1_default: spi1_default {
        group1 {
            psels = <NRF_PSEL(SPIM_SCK, 0, 28)>,					 
                    <NRF_PSEL(SPIM_MOSI, 0, 29)>,
                    <NRF_PSEL(SPIM_MISO, 0, 31)>;
        };
    };
    spi1_sleep: spi1_sleep {
        group1 {
            psels = <NRF_PSEL(SPIM_SCK, 0, 28)>,
                    <NRF_PSEL(SPIM_MOSI, 0, 29)>,
                    <NRF_PSEL(SPIM_MISO, 0, 31)>;
            low-power-enable;
        };
    };
};
/{
    buttons {
        compatible = "gpio-keys";
        button4: button_4 {
            gpios = <&gpio0 27 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
            label = "Push button switch 4";
            zephyr,code = <INPUT_KEY_4>;
        };
    };
    leds {
		compatible = "gpio-leds";
		led4: led_4 {
			gpios = <&gpio0 30 GPIO_ACTIVE_LOW>;
			label = "Green LED 4";
		};
        led5: led_5 {
			gpios = <&gpio0 26 GPIO_ACTIVE_LOW>;
			label = "Green LED 5";
		};
    };

    /* These aliases are provided for compatibility with samples */
    aliases {
        sw4 = &button4;
        led4 = &led4;
        led5 = &led5;
    };
};

And this is how I'm currently doing the power-up sequence:

static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios);
static const struct gpio_dt_spec motion_pin  = GPIO_DT_SPEC_GET(MOTION_NODE, gpios);
static const struct gpio_dt_spec ncs_pin = GPIO_DT_SPEC_GET(DT_ALIAS(led4), gpios);
static const struct gpio_dt_spec nreset_pin = GPIO_DT_SPEC_GET(DT_ALIAS(led5), gpios);
const struct spi_dt_spec spispec = SPI_DT_SPEC_GET(DT_NODELABEL(bme280), SPIOP, 0);
const struct motion_burst *pMotionBurstData;

static void power_up_sequence(void){
	k_msleep(50);
	//drive NCS pin high and then low
	gpio_pin_set_dt(&ncs_pin,1);
	k_msleep(1);
	gpio_pin_set_dt(&ncs_pin,0);
	paw_write_reg(POWER_UP_RESET_REG, 0x5A);
	k_msleep(5);
	power_up_init_reg();
	uint8_t value;
	for(uint8_t i = 0x02; i<=0x06; i++){
		paw_read_regs(i, value, 1);
	}
}

void cb(const struct device *dev, struct gpio_callback *cb, uint32_t pins){
	//read motion burst
	// update_values_motion_burst();
	gpio_pin_toggle_dt(&led);
}

int main(void)
{
	int err;

	if (!gpio_is_ready_dt(&led) || !gpio_is_ready_dt(&motion_pin) || !gpio_is_ready_dt(&ncs_pin)) {
		return 0;
	}
	err = spi_is_ready_dt(&spispec);
	if (!err) {
		LOG_ERR("Error: SPI device is not ready, err: %d", err);
		return 0;
	}
	
	gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
	gpio_pin_configure_dt(&ncs_pin, GPIO_OUTPUT_ACTIVE);
	gpio_pin_configure_dt(&nreset_pin, GPIO_OUTPUT_ACTIVE);
	gpio_pin_configure_dt(&motion_pin, GPIO_INPUT);
	
	gpio_pin_set_dt(&nreset_pin,1);
	k_usleep(10);
	gpio_pin_set_dt(&nreset_pin,0);
	power_up_sequence();			//Power on reset for the sensor

	gpio_pin_interrupt_configure_dt(&motion_pin, GPIO_INT_EDGE_TO_ACTIVE);
	static struct gpio_callback motion_cb_data;
	gpio_init_callback(&motion_cb_data,cb,BIT(motion_pin.pin));
	gpio_add_callback(motion_pin.port, &motion_cb_data);
	uint8_t x[12] = {1,2,3,4,5,6,7,8,9,10,11,12};
	pMotionBurstData = &x;
	while (1) {
		
		// LOG_INF("%d\n%d\n%d\n%d", pMotionBurstData->Del_X_H, pMotionBurstData->Del_X_L, pMotionBurstData->Del_Y_H, pMotionBurstData->Del_Y_L);
		// update_values_motion_burst();
		uint8_t val=0;
		LOG_INF("Values are:\n");
		paw_read_regs(0x0C,val,1);  //default value 0x01
		LOG_INF("%x\n",val);
		// paw_read_regs(0x02,&val,1);
		// LOG_INF("%x\n",val);
		// paw_read_regs(0x03,&val,1);
		// LOG_INF("%x\n",val);
		// paw_read_regs(0x04,&val,1);
		// LOG_INF("%x\n",val);
		// paw_read_regs(0x05,&val,1);
		// LOG_INF("%x\n",val);
		k_msleep(SLEEP_TIME_MS);
	}
	return 0;
}

This is the power-up Sequence as described in the datasheet:

The power-up initialisation mentioned in point 6 basically involves writing to a bunch of registers on the PAW3395.

What is the best method to do step 3 in the sequence?

Thank you in advance,

Regards

Parents Reply Children
Related