void bcm2835_pwm_set_clock(uint32_t divisor) { // From Gerts code divisor &= 0xfff; // Stop PWM clock bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, BCM2835_PWM_PASSWRD | 0x01); bcm2835_delay(110); // Prevents clock going slow // Wait for the clock to be not busy while ((bcm2835_peri_read(bcm2835_clk + BCM2835_PWMCLK_CNTL) & 0x80) != 0) bcm2835_delay(1); // set the clock divider and enable PWM clock bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_DIV, BCM2835_PWM_PASSWRD | (divisor << 12)); bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, BCM2835_PWM_PASSWRD | 0x11); // Source=osc and enable }
/* Writes (and reads) a single byte to SPI with manual chip select by user */ uint8_t bcm2835_spi_transfer_prototype(uint8_t value) { volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4; uint32_t returnValue; /* Clear TX and RX fifos */ // bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR); /* Maybe wait for TXD */ while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD)) { } /* Write to FIFO, With barrier */ // bcm2835_peri_write_nb(fifo, value); bcm2835_peri_write(fifo, value); printf("\nbcm2835_spi_transfer_prototype: Store Write FIFO: %09X \n", *fifo); /* Wait for DONE to be set */ while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_DONE)) ; /* Read any byte that was sent back by the slave while we sere sending to it */ //returnValue = bcm2835_peri_read_nb(fifo); returnValue = bcm2835_peri_read(fifo); // returnValue = bcm2835_peri_read(paddr); printf("\nFunction > bcm2835_spi_transfer_prototype > Return Value: %08X\n", returnValue); return returnValue; }
// Write a 1 to clear the bit in EDS void bcm2835_gpio_set_eds(uint8_t pin) { volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4 + pin/32; uint8_t shift = pin % 32; uint32_t value = 1 << shift; bcm2835_peri_write(paddr, value); }
void bcm2835_spi_begin(uint8_t cs) { volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS / 4; DBG_MSG("IN cs=%d\n", cs); // Set the SPI0 pins to the Alt 0 function to enable SPI0 access on them // except if we need custom Chip Select Pin // printf("bcm2835_spi_begin -> spi_custom_cs = %d \n",cs ); // Do we need custom chip select control or // drive CE1 manually (because CE1 does not work with hardware) if ( cs > BCM2835_SPI_CS_NONE || cs == BCM2835_SPI_CS1 ) { // indicate we will use a custom GPIO port spi_custom_cs = cs ; // ok hard CE1 not working, drive it manually if (cs == BCM2835_SPI_CS1) { // Dirty Hack CE1 in now custom Chip Select GPIO 26 // the real CE1 pin spi_custom_cs = RPI_GPIO_P1_26; bcm2835_gpio_fsel(spi_custom_cs, BCM2835_GPIO_FSEL_OUTP); // BCM2835_GPIO_FSEL_OUTP=0b001 bcm2835_gpio_write(spi_custom_cs, HIGH); } // Mask in we use custom CS (not sure it has a real effect) bcm2835_peri_set_bits(paddr, BCM2835_SPI_CS_NONE, BCM2835_SPI0_CS_CS); } // Ok hardware driving of chip select else { // Just in case spi_custom_cs = 0 ; // Mask in the CS bits of CS bcm2835_peri_set_bits(paddr, cs, BCM2835_SPI0_CS_CS); } // Now we can drive the I/O as asked if (spi_custom_cs == 0) { // Not custom CS, so hardware driven bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_ALT0); // CE0 bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_ALT0); // CE1 } else { // so set custom CS as output, High level by default bcm2835_gpio_fsel(spi_custom_cs, BCM2835_GPIO_FSEL_OUTP); // Custom GPIO bcm2835_gpio_write(spi_custom_cs, HIGH); } // Classic pin, hardware driven bcm2835_gpio_fsel(RPI_GPIO_P1_21, BCM2835_GPIO_FSEL_ALT0); // MISO bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_ALT0); // MOSI bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_ALT0); // CLK // Set the SPI CS register to the some sensible defaults bcm2835_peri_write(paddr, 0); // All 0s // Clear TX and RX fifos bcm2835_peri_write_nb(paddr, BCM2835_SPI0_CS_CLEAR); }
/* Set GPIO pad behaviour for groups of GPIOs // powerup value for all pads is // BCM2835_PAD_SLEW_RATE_UNLIMITED | BCM2835_PAD_HYSTERESIS_ENABLED | BCM2835_PAD_DRIVE_8mA */ void bcm2835_gpio_set_pad(uint8_t group, uint32_t control) { if (bcm2835_pads == MAP_FAILED) return; volatile uint32_t* paddr = bcm2835_pads + BCM2835_PADS_GPIO_0_27/4 + group; bcm2835_peri_write(paddr, control | BCM2835_PAD_PASSWRD); }
// ***************************************************************************** // I2C write register using register offset // ***************************************************************************** void bcm2835_write_i2c(uint8_t offset,uint32_t value) { volatile uint32_t* paddr; if(offset) paddr = i2c0 + offset/4; else paddr = i2c0; bcm2835_peri_write(paddr, value); }
// defaults to 0x5dc, should result in a 166.666 kHz I2C clock frequency. // The divisor must be a power of 2. Odd numbers // rounded down. void bcm2835_i2c_setClockDivider(uint16_t divider) { volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_DIV/4; bcm2835_peri_write(paddr, divider); // Calculate time for transmitting one byte // 1000000 = micros seconds in a second // 9 = Clocks per byte : 8 bits + ACK i2c_byte_wait_us = ((float)divider / BCM2835_CORE_CLK_HZ) * 1000000 * 9; }
void bcm2835_pwm_set_clock(uint32_t divisor) { if ( bcm2835_clk == MAP_FAILED || bcm2835_pwm == MAP_FAILED) return; /* bcm2835_init() failed or not root */ /* From Gerts code */ divisor &= 0xfff; /* Stop PWM clock */ bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, BCM2835_PWM_PASSWRD | 0x01); bcm2835_delay(110); /* Prevents clock going slow */ /* Wait for the clock to be not busy */ while ((bcm2835_peri_read(bcm2835_clk + BCM2835_PWMCLK_CNTL) & 0x80) != 0) bcm2835_delay(1); /* set the clock divider and enable PWM clock */ bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_DIV, BCM2835_PWM_PASSWRD | (divisor << 12)); bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, BCM2835_PWM_PASSWRD | 0x11); /* Source=osc and enable */ }
void bcm2835_i2c_setSlaveAddress(uint8_t addr) { // Set I2C Device Address #ifdef I2C_V1 volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_A/4; #else volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_A/4; #endif bcm2835_peri_write(paddr, addr); }
// set I2C clock divider by means of a baudrate number void bcm2835_i2c_set_baudrate(uint32_t baudrate) { volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_DIV/4; uint32_t divider; // use 0xFFFE mask to limit a max value and round down any odd number divider = (BCM2835_CORE_CLK_HZ / baudrate) & 0xFFFE; bcm2835_peri_write(paddr, divider); }
//void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value); /// Call bcm2835_peri_write() with 2 parameters /// \par Refer /// \par Modify void ope_peri_write(void) { volatile uint32_t* paddr; uint32_t value; get_int_code(); get_int_code(); paddr = *((volatile uint32_t **)(buff+1)); value = *((volatile uint32_t *)(buff+5)); bcm2835_peri_write( paddr, value ); // set_ope_code( OPE_PERI_WRITE ); }
// initialization of GPIO and SPI // ---------------------------------------------------------- void TFT_init_board ( void ) { // *************** set the pins to be an output and turn them on bcm2835_gpio_fsel( OE, BCM2835_GPIO_FSEL_OUTP ); bcm2835_gpio_write( OE, HIGH ); bcm2835_gpio_fsel( RAIO_RST, BCM2835_GPIO_FSEL_OUTP ); bcm2835_gpio_write( RAIO_RST, HIGH ); bcm2835_gpio_fsel( RAIO_CS, BCM2835_GPIO_FSEL_OUTP ); bcm2835_gpio_write( RAIO_CS, HIGH ); bcm2835_gpio_fsel( RAIO_RS, BCM2835_GPIO_FSEL_OUTP ); bcm2835_gpio_write( RAIO_RS, HIGH ); bcm2835_gpio_fsel( RAIO_WR, BCM2835_GPIO_FSEL_OUTP ); bcm2835_gpio_write( RAIO_WR, HIGH ); bcm2835_gpio_fsel( RAIO_RD, BCM2835_GPIO_FSEL_OUTP ); bcm2835_gpio_write( RAIO_RD, HIGH ); // *************** now the inputs bcm2835_gpio_fsel( RAIO_WAIT, BCM2835_GPIO_FSEL_INPT ); bcm2835_gpio_set_pud( RAIO_WAIT, BCM2835_GPIO_PUD_UP); bcm2835_gpio_fsel( RAIO_INT, BCM2835_GPIO_FSEL_INPT ); bcm2835_gpio_set_pud( RAIO_INT, BCM2835_GPIO_PUD_UP); // *************** set pins for SPI bcm2835_gpio_fsel(MISO, BCM2835_GPIO_FSEL_ALT0); bcm2835_gpio_fsel(MOSI, BCM2835_GPIO_FSEL_ALT0); bcm2835_gpio_fsel(SCLK, BCM2835_GPIO_FSEL_ALT0); bcm2835_gpio_fsel(SPI_CE1, BCM2835_GPIO_FSEL_ALT0); // set the SPI CS register to the some sensible defaults volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/8; bcm2835_peri_write( paddr, 0 ); // All 0s // clear TX and RX fifos bcm2835_peri_write_nb( paddr, BCM2835_SPI0_CS_CLEAR ); bcm2835_spi_setBitOrder( BCM2835_SPI_BIT_ORDER_MSBFIRST ); bcm2835_spi_setDataMode( BCM2835_SPI_MODE0 ); bcm2835_spi_setClockDivider( BCM2835_SPI_CLOCK_DIVIDER_2 ); bcm2835_spi_chipSelect( BCM2835_SPI_CS1 ); bcm2835_spi_setChipSelectPolarity( BCM2835_SPI_CS1, LOW ); }
void bcm2835_spi_begin(void) { // Set the SPI0 pins to the Alt 0 function to enable SPI0 access on them bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_ALT0); // CE1 bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_ALT0); // CE0 bcm2835_gpio_fsel(RPI_GPIO_P1_21, BCM2835_GPIO_FSEL_ALT0); // MISO bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_ALT0); // MOSI bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_ALT0); // CLK // Set the SPI CS register to the some sensible defaults volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; bcm2835_peri_write(paddr, 0); // All 0s // Clear TX and RX fifos bcm2835_peri_write_nb(paddr, BCM2835_SPI0_CS_CLEAR); }
//!>>>>>>>>>>>>>>>>> //!>>>>>>>>>>>>>>>>> //! Slave Select Lines must be toggled manually with this function extern void bcm2835_spi_write_prototype(char buf) { volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; volatile uint32_t* fifo = bcm2835_spi0 + BCM2835_SPI0_FIFO/4; uint32_t i; uint32_t tempStoreVal; /* This is Polled transfer as per section 10.6.1 // BUG ALERT: what happens if we get interupted in this section, and someone else // accesses a different peripheral? // Answer: an ISR is required to issue the required memory barriers. */ /* Clear TX and RX fifos */ //bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR); /* Set TA = 1 */ // bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA); { /* Maybe wait for TXD */ while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD)) // Wait until it can accept data ; /* Write to FIFO, WITH!!!!>>>> barrier */ bcm2835_peri_write(fifo, buf); // printf("\nFunction bcm2835_spi_write_prototype > FIFO: %02X\n", *fifo); /* Read from FIFO to prevent stalling */ while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD) // Wait until transmission is completed (void) bcm2835_peri_read_nb(fifo); } /* Wait for DONE to be set */ while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_DONE)) { while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD) (void) bcm2835_peri_read(fifo); // printf("\nFIFO - %zu\n", bcm2835_peri_read_nb(fifo)); }; printf("\nFunction bcm2835_spi_write_prototype > Write: %02X\n", buf); /* Set TA = 0, and also set the barrier */ // bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA); }
// --------------------------------------------------------------------------- // Enables SPI function on default GPIOs. // --------------------------------------------------------------------------- void bcm2835_spi_open( void ) { // This driver uses the default pins with GPFSEL alternative function ALT0. bcm2835_gpio_fsel( SPI_GPIO_CE0, BCM2835_GPFSEL_ALT0 ); bcm2835_gpio_fsel( SPI_GPIO_CE1, BCM2835_GPFSEL_ALT0 ); bcm2835_gpio_fsel( SPI_GPIO_MISO, BCM2835_GPFSEL_ALT0 ); bcm2835_gpio_fsel( SPI_GPIO_MOSI, BCM2835_GPFSEL_ALT0 ); bcm2835_gpio_fsel( SPI_GPIO_CLK, BCM2835_GPFSEL_ALT0 ); // Set SPI CS register to default values (0). volatile uint32_t *paddr; paddr = bcm2835_spi0 + BCM2835_SPI0_CS / 4; bcm2835_peri_write( paddr, 0 ); // Clear FIFOs. bcm2835_peri_write_nb( paddr, BCM2835_SPIO_CS_CLEAR ); }
void bcm2835_spi_begin(void) { volatile uint32_t* paddr; /* Set the SPI0 pins to the Alt 0 function to enable SPI0 access on them */ bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_ALT0); /* CE1 */ bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_ALT0); /* CE0 */ bcm2835_gpio_fsel(RPI_GPIO_P1_21, BCM2835_GPIO_FSEL_ALT0); /* MISO */ bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_ALT0); /* MOSI */ bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_ALT0); /* CLK */ /* Set the SPI CS register to the some sensible defaults */ paddr = bcm2835_spi0 + BCM2835_SPI0_CS/4; bcm2835_peri_write(paddr, 0); /* All 0s */ /* Clear TX and RX fifos */ bcm2835_peri_write_nb(paddr, BCM2835_SPI0_CS_CLEAR); }
// Set output pin static __inline__ void bcm2835_gpio_set(uint8_t pin) { volatile uint32_t* paddr = gpio + BCM2835_GPSET0/4 + pin/32; uint8_t shift = pin % 32; bcm2835_peri_write(paddr, 1 << shift); }
// Pullup/down clock // Clocks the value of pud into the GPIO pin void bcm2835_gpio_pudclk(uint8_t pin, uint8_t on) { volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPPUDCLK0/4 + pin/32; uint8_t shift = pin % 32; bcm2835_peri_write(paddr, (on ? 1 : 0) << shift); }
// Set pullup/down void bcm2835_gpio_pud(uint8_t pud) { volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPPUD/4; bcm2835_peri_write(paddr, pud); }
// Set/clear only the bits in value covered by the mask void bcm2835_peri_set_bits(volatile u32 * paddr, u32 value, u32 mask) { u32 v = bcm2835_peri_read(paddr); v = (v & ~mask) | (value & mask); bcm2835_peri_write(paddr, v); }
// Clear all output pins in the mask void bcm2835_gpio_clr_multi(uint32_t mask) { volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPCLR0/4; bcm2835_peri_write(paddr, mask); }
// Clear output pin void bcm2835_gpio_clr(uint8_t pin) { volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPCLR0/4 + pin/32; uint8_t shift = pin % 32; bcm2835_peri_write(paddr, 1 << shift); }
void bcm2835_gpio_set_eds_multi(uint32_t mask) { volatile uint32_t* paddr = bcm2835_gpio + BCM2835_GPEDS0/4; bcm2835_peri_write(paddr, mask); }
/* Set/clear only the bits in value covered by the mask * This is not atomic - can be interrupted. */ void bcm2835_peri_set_bits(volatile uint32_t* paddr, uint32_t value, uint32_t mask) { uint32_t v = bcm2835_peri_read(paddr); v = (v & ~mask) | (value & mask); bcm2835_peri_write(paddr, v); }
/* Read an number of bytes from I2C sending a repeated start after writing // the required register. Only works if your device supports this mode */ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len) { #ifdef I2C_V1 volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4; volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4; volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4; volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4; #else volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN/4; volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; #endif uint32_t remaining = len; uint32_t i = 0; uint8_t reason = BCM2835_I2C_REASON_OK; /* Clear FIFO */ bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 ); /* Clear Status */ bcm2835_peri_write(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); /* Set Data Length */ bcm2835_peri_write(dlen, 1); /* Enable device and start transfer */ bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN); bcm2835_peri_write(fifo, regaddr[0]); bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); /* poll for transfer has started */ while ( !( bcm2835_peri_read(status) & BCM2835_BSC_S_TA ) ) { /* Linux may cause us to miss entire transfer stage */ if(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE) break; } /* Send a repeated start with read bit set in address */ bcm2835_peri_write(dlen, len); bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ ); /* Wait for write to complete and first byte back. */ bcm2835_delayMicroseconds(i2c_byte_wait_us * 3); /* wait for transfer to complete */ while (!(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE)) { /* we must empty the FIFO as it is populated and not use any delay */ while (remaining && bcm2835_peri_read(status) & BCM2835_BSC_S_RXD) { /* Read from FIFO */ buf[i] = bcm2835_peri_read(fifo); i++; remaining--; } } /* transfer has finished - grab any remaining stuff in FIFO */ while (remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_RXD)) { /* Read from FIFO */ buf[i] = bcm2835_peri_read(fifo); i++; remaining--; } /* Received a NACK */ if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) { reason = BCM2835_I2C_REASON_ERROR_NACK; } /* Received Clock Stretch Timeout */ else if (bcm2835_peri_read(status) & 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(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE); return reason; }
/* Writes an number of bytes to I2C */ uint8_t bcm2835_i2c_write(const char * buf, uint32_t len) { #ifdef I2C_V1 volatile uint32_t* dlen = bcm2835_bsc0 + BCM2835_BSC_DLEN/4; volatile uint32_t* fifo = bcm2835_bsc0 + BCM2835_BSC_FIFO/4; volatile uint32_t* status = bcm2835_bsc0 + BCM2835_BSC_S/4; volatile uint32_t* control = bcm2835_bsc0 + BCM2835_BSC_C/4; #else volatile uint32_t* dlen = bcm2835_bsc1 + BCM2835_BSC_DLEN/4; volatile uint32_t* fifo = bcm2835_bsc1 + BCM2835_BSC_FIFO/4; volatile uint32_t* status = bcm2835_bsc1 + BCM2835_BSC_S/4; volatile uint32_t* control = bcm2835_bsc1 + BCM2835_BSC_C/4; #endif uint32_t remaining = len; uint32_t i = 0; uint8_t reason = BCM2835_I2C_REASON_OK; /* Clear FIFO */ bcm2835_peri_set_bits(control, BCM2835_BSC_C_CLEAR_1 , BCM2835_BSC_C_CLEAR_1 ); /* Clear Status */ bcm2835_peri_write(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE); /* Set Data Length */ bcm2835_peri_write(dlen, len); /* pre populate FIFO with max buffer */ while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) ) { bcm2835_peri_write_nb(fifo, buf[i]); i++; remaining--; } /* Enable device and start transfer */ bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST); /* Transfer is over when BCM2835_BSC_S_DONE */ while(!(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE )) { while ( remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_TXD )) { /* Write to FIFO */ bcm2835_peri_write(fifo, buf[i]); i++; remaining--; } } /* Received a NACK */ if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) { reason = BCM2835_I2C_REASON_ERROR_NACK; } /* Received Clock Stretch Timeout */ else if (bcm2835_peri_read(status) & 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(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE); return reason; }
void bcm2835_i2c_setSlaveAddress(uint8_t addr) { // Set I2C Device Address volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_A/4; bcm2835_peri_write(paddr, addr); }
/* defaults to 0, which means a divider of 65536. // The divisor must be a power of 2. Odd numbers // rounded down. The maximum SPI clock rate is // of the APB clock */ void bcm2835_spi_setClockDivider(uint16_t divider) { volatile uint32_t* paddr = bcm2835_spi0 + BCM2835_SPI0_CLK/4; bcm2835_peri_write(paddr, divider); }
// Set all output pins in the mask void bcm2835_gpio_set_multi(uint32_t mask) { uint32_t* paddr = bcm2835_gpio + BCM2835_GPSET0/4; bcm2835_peri_write(paddr, mask); }
// Set GPIO pad behaviour for groups of GPIOs // powerup value for al pads is // BCM2835_PAD_SLEW_RATE_UNLIMITED | BCM2835_PAD_HYSTERESIS_ENABLED | BCM2835_PAD_DRIVE_8mA void bcm2835_gpio_set_pad(uint8_t group, uint32_t control) { volatile uint32_t* paddr = bcm2835_pads + BCM2835_PADS_GPIO_0_27/4 + group*2; bcm2835_peri_write(paddr, control | BCM2835_PAD_PASSWRD); }