Ejemplo n.º 1
0
/**
@ingroup spi_function
@brief Setup and initialize new SPI instance.

Setup and create SPI instance according to parameters.

@note This must be called exactly once per new SPI instance.
@note Slave mode is not implemented!!!

@return handle to the SPI instance created. Should be used as parameter to the send() functions.

@param mode SPI_MODE_MASTER: Master mode\n
SPI_MODE_SLAVE: Slave Mode.
@param clock_divider defines the SPI clock divider. Use SPI_CLOCK_DIVIDER_xx as parameter.
@param spi_mode defines the SPI mode to use [0..3]. These are the standard modes specified by Motorola\n
|spi_mode | CPOL | CPHA |Clock Behavior|
|:---:    |:----:|:----:|:----------|
| 0       | 0    | 0    |Low when idle, samples on leading edge|
| 1       | 0    | 1    |Low when idle, samples on trailing edge|
| 2       | 1    | 0    |High when idle, samples on leading edge|
| 3       | 1    | 1    |High when idle, samples on trailing edge|

@param data_order SPI_DATA_ORDER_LSB: LSB transmitted first.\n
SPI_DATA_ORDER_MSB: MSB transmitted first.
@param *cs_port port register for the CS pin - Ex. PORTB.
@param *cs_pin that is connected to the slaves CS - Ex. PB6.
@param  cs_active_level 0: CS active when low.\n
1: CS active when high.
@param *rx_buf 0: No receive buffer used, means no data vil be received from slave.\n
pointer to the receive buffer structure to store received data in.
@param *tx_buf 0: No trasmit buffer used, means that only one byte can be transmitted at the time.\n
pointer to the transmit buffer structure to store transmit data in.
0: no tx buffer wanted.
@param *call_back pointer to a call back function that will be called when the driver receives a byte from the SPI bus. The function should have the following signature:\n
@code
void handler_name(spi_p spi_instance, uint8_t rx_byte)
@endcode
0: no call back function will be called.

@note If SPI_USE_BUFFER in spi_iha_config.h is 0 then the pointers rx_buf and tx_buf are ignored.
*/
spi_p spi_new_instance(uint8_t mode, int8_t clock_divider, uint8_t spi_mode, uint8_t data_order, volatile uint8_t *cs_port, uint8_t cs_pin, uint8_t cs_active_level,
buffer_struct_t *rx_buf, buffer_struct_t *tx_buf, void(*call_back )(spi_p spi, uint8_t last_rx_byte))
{
	if (!_initialised) {
		_spi_init();
		_initialised = 1;
	}
	
	spi_p _spi = malloc(sizeof *_spi);
	
	_spi->_cs_port = cs_port;
	_spi->_cs_pin = cs_pin;
	
	// Set CS pin to output
	*(cs_port-1) |= _BV(cs_pin);
	
	_spi->_cs_active_level = cs_active_level;
	_spi->_SPCR = mode | _prescaler_mask[clock_divider] |(spi_mode<<2) | data_order;
	
	if (clock_divider > 3) {
		_spi->_SPSR = _BV(SPI2X);
	}

	#if SPI_USE_BUFFER == 1
	_spi->_tx_buf = tx_buf;
	_spi->_rx_buf = rx_buf;
	#endif

	_spi->_call_back = call_back;

	// Critical section
	{
		// disable interrupt
		uint8_t c_sreg = SREG;
		cli();

		spi_p current_instance = _this;
		_this = _spi;
		_set_cs(CS_INACTIVE);
		_this = current_instance;

		// restore interrupt state
		SREG = c_sreg;
	}

	return _spi;
}