Пример #1
0
/**
 * @ingroup SPI
 *
 * Transfers any number of bytes to the currently selected SPI slave.
 * Asserts the currently selected CS pins (as previously set by \ref bcm2835_spi_chipSelect)
 * during the transfer.
 *
 * @param tbuf Buffer of bytes to send.
 * @param len Number of bytes in the tbuf buffer, and the number of bytes to send.
 */
void bcm2835_spi_writenb(const char* tbuf, const uint32_t len) {
	uint32_t i;

	// Clear TX and RX fifos
	BCM2835_PERI_SET_BITS(BCM2835_SPI0->CS, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR);
	// Set TA = 1
	BCM2835_PERI_SET_BITS(BCM2835_SPI0->CS, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA);

	for (i = 0; i < len; i++) {
		// Maybe wait for TXD
		while (!(BCM2835_SPI0->CS & BCM2835_SPI0_CS_TXD))
			;
		// Write to FIFO
		BCM2835_SPI0->FIFO = (uint32_t) tbuf[i];

		while ((BCM2835_SPI0->CS & BCM2835_SPI0_CS_RXD)) {
			(void) BCM2835_SPI0->FIFO;
		}
	}

	// Wait for DONE to be set
	while (!(BCM2835_SPI0->CS & BCM2835_SPI0_CS_DONE)) {
		while ((BCM2835_SPI0->CS & BCM2835_SPI0_CS_RXD)) {
			(void) BCM2835_SPI0->FIFO;
		}
	}

	// Set TA = 0
	BCM2835_PERI_SET_BITS(BCM2835_SPI0->CS, 0, BCM2835_SPI0_CS_TA);
}
Пример #2
0
/**
 *
 * @param dmx_device_info
 */
static void ws2812_zero(dmx_device_info_t *dmx_device_info, const uint8_t *dmx_data) {
	int i,j;

	bcm2835_spi_setClockDivider((uint16_t) ((uint32_t) BCM2835_CORE_CLK_HZ / (uint32_t) 6400000));
	bcm2835_spi_chipSelect(dmx_device_info->device_info.chip_select);					// Just in case we have a multiplexer
	bcm2835_spi_setChipSelectPolarity(dmx_device_info->device_info.chip_select, LOW);	// Just in case we have a multiplexer
	// Clear TX and RX fifos
	BCM2835_PERI_SET_BITS(BCM2835_SPI0->CS, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR);
	// Set TA = 1
	BCM2835_PERI_SET_BITS(BCM2835_SPI0->CS, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA);

	for (i = 0; i < ((int) dmx_device_info->pixel_count * (int) WS2812_SLOTS_PER_PIXEL); i++) {
		for (j = 0; j < 8; j++) {
			// Maybe wait for TXD
			while (!(BCM2835_SPI0->CS & BCM2835_SPI0_CS_TXD))
				;

			BCM2835_SPI0->FIFO = (uint32_t) WS2812_LOW_CODE;

			while ((BCM2835_SPI0->CS & BCM2835_SPI0_CS_RXD)) {
				(void) BCM2835_SPI0->FIFO;
			}
		}
	}

	// Wait for DONE to be set
	while (!(BCM2835_SPI0->CS & BCM2835_SPI0_CS_DONE)) {
		while ((BCM2835_SPI0->CS & BCM2835_SPI0_CS_RXD)) {
			(void) BCM2835_SPI0->FIFO;
		}
	}

	// Set TA = 0
	BCM2835_PERI_SET_BITS(BCM2835_SPI0->CS, 0, BCM2835_SPI0_CS_TA);
}
Пример #3
0
void bcm2835_spi_writenb(char* tbuf, uint32_t len)
{
    // Clear TX and RX fifos
	BCM2835_PERI_SET_BITS(BCM2835_SPI0->CS, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR);

    // Set TA = 1
	BCM2835_PERI_SET_BITS(BCM2835_SPI0->CS, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA);

    uint32_t i;
	for (i = 0; i < len; i++)
	{
		// Maybe wait for TXD
		while (!(BCM2835_SPI0->CS & BCM2835_SPI0_CS_TXD))
			;

		// Write to FIFO, no barrier
		BCM2835_SPI0->FIFO =  tbuf[i];
	}

    // Wait for DONE to be set
    while (!(BCM2835_SPI0->CS & BCM2835_SPI0_CS_DONE))
    	;

    // Set TA = 0, and also set the barrier
	BCM2835_PERI_SET_BITS(BCM2835_SPI0->CS, 0, BCM2835_SPI0_CS_TA);
}
Пример #4
0
void inline bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len)
{
	// Clear TX and RX fifos
	BCM2835_PERI_SET_BITS(BCM2835_SPI0->CS, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR);

    // Set TA = 1
	BCM2835_PERI_SET_BITS(BCM2835_SPI0->CS, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA);

    uint32_t i;
    for (i = 0; i < len; i++)
    {
		// Maybe wait for TXD
		while (!(BCM2835_SPI0->CS & BCM2835_SPI0_CS_TXD))
			;

		// Write to FIFO, no barrier
		//PUT32(BCM2835_SPI0_FIFO, tbuf[i]);
		BCM2835_SPI0->FIFO = tbuf[i];

		// Wait for RXD
		while (!(BCM2835_SPI0->CS & BCM2835_SPI0_CS_RXD))
			;

		// then read the data byte
		rbuf[i] = BCM2835_SPI0->FIFO;
    }
    // Wait for DONE to be set
    while (!(BCM2835_SPI0->CS & BCM2835_SPI0_CS_DONE))
        	;

    // Set TA = 0, and also set the barrier
    BCM2835_PERI_SET_BITS(BCM2835_SPI0->CS, 0, BCM2835_SPI0_CS_TA);
}
Пример #5
0
uint8_t bcm2835_i2c_read(char* buf, uint32_t len)
{
    uint32_t remaining = len;
    uint32_t i = 0;
    uint8_t reason = BCM2835_I2C_REASON_OK;

    // Clear FIFO
    BCM2835_PERI_SET_BITS(BCM2835_BSC1->C, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 );
    // Clear Status
    BCM2835_BSC1->S = BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE;
	// Set Data Length
    BCM2835_BSC1->DLEN = len;
    // Start read
    BCM2835_BSC1->C = BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ;

	// wait for transfer to complete
	while (!(BCM2835_BSC1->S & BCM2835_BSC_S_DONE)) {
		// we must empty the FIFO as it is populated and not use any delay
		while (BCM2835_BSC1->S & BCM2835_BSC_S_RXD) {
			// Read from FIFO, no barrier
			buf[i] = BCM2835_BSC1 ->FIFO;
			i++;
			remaining--;
		}
	}

	// transfer has finished - grab any remaining stuff in FIFO
	while (remaining && (BCM2835_BSC1 ->S & BCM2835_BSC_S_RXD)) {
		// Read from FIFO, no barrier
		buf[i] = BCM2835_BSC1 ->FIFO;
		i++;
		remaining--;
	}

	// Received a NACK
	if (BCM2835_BSC1 ->S & BCM2835_BSC_S_ERR) {
		reason = BCM2835_I2C_REASON_ERROR_NACK;
	}

	// Received Clock Stretch Timeout
	else if (BCM2835_BSC1 ->S & BCM2835_BSC_S_CLKT) {
		reason = BCM2835_I2C_REASON_ERROR_CLKT;
	}

	// Not all data is received
	else if (remaining) {
		reason = BCM2835_I2C_REASON_ERROR_DATA;
	}

	BCM2835_PERI_SET_BITS(BCM2835_BSC1->C, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE);

    return reason;
}
Пример #6
0
/**
 * @ingroup DEV
 *
 * @param dmx_device_info
 */
static void ws2812(dmx_device_info_t * dmx_device_info, const uint8_t *dmx_data) {
	int i;
	uint8_t mask = 0x80;
	uint16_t dmx_data_index = dmx_device_info->dmx_start_address;

	bcm2835_spi_setClockDivider((uint16_t) ((uint32_t) BCM2835_CORE_CLK_HZ / (uint32_t) 6400000));
	bcm2835_spi_chipSelect(dmx_device_info->device_info.chip_select);					// Just in case we have a multiplexer
	bcm2835_spi_setChipSelectPolarity(dmx_device_info->device_info.chip_select, LOW);	// Just in case we have a multiplexer

	// Clear TX and RX fifos
	BCM2835_PERI_SET_BITS(BCM2835_SPI0->CS, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR);
	// Set TA = 1
	BCM2835_PERI_SET_BITS(BCM2835_SPI0->CS, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA);

	for (i = 0; i < ((int)dmx_device_info->pixel_count * (int)WS2812_SLOTS_PER_PIXEL); i++) {
		if (dmx_data_index > DMX_UNIVERSE_SIZE) {
			break;
		}

		mask = 0x80;

		while (mask != 0) {
			// Maybe wait for TXD
			while (!(BCM2835_SPI0->CS & BCM2835_SPI0_CS_TXD))
				;

			if (dmx_data[dmx_data_index] & mask) {
				BCM2835_SPI0->FIFO = (uint32_t) WS2812_HIGH_CODE;
			} else {
				BCM2835_SPI0->FIFO = (uint32_t) WS2812_LOW_CODE;
			}

			while ((BCM2835_SPI0->CS & BCM2835_SPI0_CS_RXD)) {
				(void) BCM2835_SPI0->FIFO;
			}

			mask >>= 1;
		}

		dmx_data_index++;
	}

	// Wait for DONE to be set
	while (!(BCM2835_SPI0->CS & BCM2835_SPI0_CS_DONE)) {
		while ((BCM2835_SPI0->CS & BCM2835_SPI0_CS_RXD)) {
			(void) BCM2835_SPI0->FIFO;
		}
	}

	// Set TA = 0
	BCM2835_PERI_SET_BITS(BCM2835_SPI0->CS, 0, BCM2835_SPI0_CS_TA);
}
Пример #7
0
uint8_t bcm2835_i2c_write(const char * buf, uint32_t len)
{
    uint32_t remaining = len;
    uint32_t i = 0;
    uint8_t reason = BCM2835_I2C_REASON_OK;

    // Clear FIFO
    BCM2835_PERI_SET_BITS(BCM2835_BSC1->C, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 );
    // Clear Status
    BCM2835_BSC1->S = BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE;
	// Set Data Length
    BCM2835_BSC1->DLEN = len;
    // pre populate FIFO with max buffer
	while (remaining && (i < BCM2835_BSC_FIFO_SIZE)) {
		BCM2835_BSC1 ->FIFO = buf[i];
		i++;
		remaining--;
	}

    // Enable device and start transfer
    BCM2835_BSC1->C = BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST;

	// Transfer is over when BCM2835_BSC_S_DONE
	while (!(BCM2835_BSC1 ->S & BCM2835_BSC_S_DONE)) {
		while (remaining && (BCM2835_BSC1 ->S & BCM2835_BSC_S_TXD)) {
			// Write to FIFO
			BCM2835_BSC1 ->FIFO = buf[i];
			i++;
			remaining--;
    	}
    }

	// Received a NACK
	if (BCM2835_BSC1 ->S & BCM2835_BSC_S_ERR) {
		reason = BCM2835_I2C_REASON_ERROR_NACK;
	}

	// Received Clock Stretch Timeout
	else if (BCM2835_BSC1 ->S & BCM2835_BSC_S_CLKT) {
		reason = BCM2835_I2C_REASON_ERROR_CLKT;
	}

	// Not all data is sent
	else if (remaining) {
		reason = BCM2835_I2C_REASON_ERROR_DATA;
	}

	BCM2835_PERI_SET_BITS(BCM2835_BSC1->C, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE);

    return reason;
}
Пример #8
0
/**
 * @ingroup SPI
 *
 * Transfers uint16_t (2 bytes) to the currently selected SPI slave.
 * Asserts the currently selected CS pins (as previously set by \ref bcm2835_spi_chipSelect)
 * during the transfer.
 *
 * @param data uint16_t
 */
void bcm2835_spi_write(const uint16_t data) {
	dsb();
	// Clear TX and RX fifos
	BCM2835_PERI_SET_BITS(BCM2835_SPI0->CS, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR);
	// Set TA = 1
	BCM2835_PERI_SET_BITS(BCM2835_SPI0->CS, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA);
	// Maybe wait for TXD
	while (!(BCM2835_SPI0->CS & BCM2835_SPI0_CS_TXD))
		;
	// Write to FIFO
	BCM2835_SPI0->FIFO = (uint32_t) data >> 8;
	BCM2835_SPI0->FIFO = (uint32_t) data & 0xFF;
	// Wait for DONE to be set
	while (!(BCM2835_SPI0->CS & BCM2835_SPI0_CS_DONE))
		;
	// Set TA = 0
	BCM2835_PERI_SET_BITS(BCM2835_SPI0->CS, 0, BCM2835_SPI0_CS_TA);
	dmb();
}
Пример #9
0
void inline bcm2835_spi_write(uint16_t data) {
    // Clear TX and RX fifos
	BCM2835_PERI_SET_BITS(BCM2835_SPI0->CS, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR);

    // Set TA = 1
	BCM2835_PERI_SET_BITS(BCM2835_SPI0->CS, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA);

	// Maybe wait for TXD
    while (!(BCM2835_SPI0->CS & BCM2835_SPI0_CS_TXD))
		;

	// Write to FIFO
    BCM2835_SPI0->FIFO = data >> 8;
    BCM2835_SPI0->FIFO = data & 0x0FF;

    // Wait for DONE to be set
	while (!(BCM2835_SPI0->CS & BCM2835_SPI0_CS_DONE))
    	;

    // Set TA = 0, and also set the barrier
	BCM2835_PERI_SET_BITS(BCM2835_SPI0->CS, 0, BCM2835_SPI0_CS_TA);
}
Пример #10
0
void inline bcm2835_spi_chipSelect(uint8_t cs)
{
	BCM2835_PERI_SET_BITS(BCM2835_SPI0->CS, cs, BCM2835_SPI0_CS_CS);
}
Пример #11
0
void inline bcm2835_spi_setDataMode(uint8_t mode)
{
    // Mask in the CPO and CPHA bits of CS
	BCM2835_PERI_SET_BITS(BCM2835_SPI0->CS, mode << 2, BCM2835_SPI0_CS_CPOL | BCM2835_SPI0_CS_CPHA);
}
Пример #12
0
void inline bcm2835_spi_setChipSelectPolarity(uint8_t cs, uint8_t active)
{
    uint8_t shift = 21 + cs;
    // Mask in the appropriate CSPOLn bit
    BCM2835_PERI_SET_BITS(BCM2835_SPI0->CS, active << shift, 1 << shift);
}