This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Revised spi_master to utilize a mask for cs

Seeing recent response to my original question on multiple chip selects, I've opted to share a modification to spi_master that I've implemented in part to make handling some serial LCDs, which use an added command pin, easier. By using a mask instead of pin number, it allows both pins to be changed in one call and ensures the two pins are synchronized. It also allows a single function call to configure all the chip selects associated with an SPI channel which I think makes for cleaner code. I've attached the entire file, but included a few snippets to illustrate changes.

I've left the code with #define to use it in either mask or pin# mode, but honestly don't think I will ever use it in any mode other than the mask mode.

The pin_slave_select declaratuin in spi_master_instance_t was changed to

#ifdef SPI_MASK_CS
	  uint32_t mask_slave_select;	/**< Current chip select. */
	  uint32_t mask_chip_selects; /**< All chip selects			*/
#else
    uint8_t pin_slave_select;   /**< A pin for Slave Select. */
#endif**

and the spi_master_change_cs function's use of the pin_slave select was modified to:

#ifdef SPI_MASK_CS
		p_spi_instance->mask_slave_select = cs_pin;
		NRF_GPIO->OUTSET = p_spi_instance->mask_slave_select;
		NRF_GPIO->DIRSET = p_spi_instance->mask_slave_select;
		NRF_GPIO->OUTSET = p_spi_instance->mask_slave_select;
#else
	p_spi_instance->pin_slave_select = cs_pin;
    //A Slave select must be set as high before setting it as output,
    //because during connect it to the pin it causes glitches.
    nrf_gpio_pin_set(p_spi_instance->pin_slave_select);
    nrf_gpio_cfg_output(p_spi_instance->pin_slave_select);
    nrf_gpio_pin_set(p_spi_instance->pin_slave_select);
#endif

And spi_send_recv updated to

#ifdef SPI_MASK_CS
	NRF_GPIO->OUTCLR = p_spi_instance->mask_slave_select;
#else					
    nrf_gpio_pin_clear(p_spi_instance->pin_slave_select);
#endif

My LCD initialization code looks like this:

#define SPI_MASK_CS
#define LCD_CS_MASK 0x00040000 /**< The value of bit 18 */
#define LCD_A0_MASK 0x00080000 /**< The value of bit 19 */
#define LCD_D0_MASK 0x00000000
#define LCD_CMND_MASK (LCD_A0_MASK | LCD_CS_MASK)
#define LCD_DATA_MASK (LCD_D0_MASK | LCD_CS_MASK)

		spi_master_change_cs(LCD_SPI, LCD_CMND_MASK);

		init_buf(m_tx_data_spi, m_rx_data_spi, TX_RX_MSG_LENGTH, 0);
		m_tx_data_spi[0] = 0xA2; //LCD bias set
		m_tx_data_spi[1] = 0xA0; //SEQ correspondance normal
		m_tx_data_spi[2] = 0xC8; //COM dir reverse
            ...
		m_tx_data_spi[9] = 0x81; //set Vs (CONTRAST)
		m_tx_data_spi[10] = LCDcontrast;//value
		m_tx_data_spi[11] = 0xA6;//display normal
		m_tx_data_spi[12] = 0xAF;//display on
   		len = 13;
		lcd_spi_send_recv(LCD_SPI, m_tx_data_spi, m_rx_data_spi, len);

The entire modified SDK8 version of spi_master spi_master.c

Related