Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added support for I2C Oled

Rewrited I2C code of BCM2835
Added I2C Oled support
Speed coding, I need to cleanup the code later
  • Loading branch information...
commit 6e986fa7b08f0680d1be50584830bc152151280d 1 parent 615cc26
@hallard authored
View
226 Adafruit_SSD1306.cpp
@@ -181,7 +181,8 @@ boolean Adafruit_SSD1306::init(int8_t RST,int16_t SSD1306_LCDWIDTH, int16_t SSD1
return false;
// Init Raspberry PI I2C
- bcm2835_i2c_begin();
+ if (bcm2835_i2c_begin()==0)
+ return false;
return ( true);
}
@@ -228,9 +229,11 @@ void Adafruit_SSD1306::begin(uint8_t vccstate, uint8_t i2caddr) {
bcm2835_i2c_setSlaveAddress(i2caddr) ;
// Set clock to 400 KHz
- bcm2835_i2c_setClockDivider(BCM2835_I2C_CLOCK_DIVIDER_626);
+ // does not seem to work, will check this later
+ // bcm2835_i2c_set_baudrate(400000);
}
+
// Setup reset pin direction (used by both SPI and I2C)
bcm2835_gpio_fsel(rst, BCM2835_GPIO_FSEL_OUTP);
bcm2835_gpio_write(rst, HIGH);
@@ -246,43 +249,72 @@ void Adafruit_SSD1306::begin(uint8_t vccstate, uint8_t i2caddr) {
// bring out of reset
bcm2835_gpio_write(rst, HIGH);
-
- // turn on VCC (9V?)
-
-
- // Init sequence for OLED module
- ssd1306_command(SSD1306_DISPLAYOFF); // 0xAE
- ssd1306_command(SSD1306_SETDISPLAYCLOCKDIV); // 0xD5
- ssd1306_command(0x80); // the suggested ratio 0x80
- ssd1306_command(SSD1306_SETMULTIPLEX); // 0xA8
-
- ssd1306_command(ssd1306_lcdheight==32?0x1F:0x3F);
-
- ssd1306_command(SSD1306_SETDISPLAYOFFSET); // 0xD3
- ssd1306_command(0x0); // no offset
- ssd1306_command(SSD1306_SETSTARTLINE | 0x0); // line #0
- ssd1306_command(SSD1306_CHARGEPUMP); // 0x8D
- ssd1306_command(vccstate==SSD1306_EXTERNALVCC?0x10:0x14);
- ssd1306_command(SSD1306_MEMORYMODE); // 0x20
- ssd1306_command(0x00); // 0x0 act like ks0108
- ssd1306_command(SSD1306_SEGREMAP | 0x1);
- ssd1306_command(SSD1306_COMSCANDEC);
- ssd1306_command(SSD1306_SETCOMPINS); // 0xDA
- ssd1306_command(ssd1306_lcdheight==32?0x02:0x12);
- ssd1306_command(SSD1306_SETCONTRAST); // 0x81
-
- if (ssd1306_lcdheight == 32)
- ssd1306_command(0x8F);
+
+ // SPI oled does not seem to work with spi multiple byte command, I need to check that later
+ if (isSPI())
+ {
+ // Init sequence for OLED module
+ ssd1306_command(SSD1306_DISPLAYOFF); // 0xAE
+ ssd1306_command(SSD1306_SETDISPLAYCLOCKDIV); // 0xD5
+ ssd1306_command(0x80); // the suggested ratio 0x80
+ ssd1306_command(SSD1306_SETMULTIPLEX); // 0xA8
+
+ ssd1306_command(ssd1306_lcdheight==32?0x1F:0x3F);
+
+ ssd1306_command(SSD1306_SETDISPLAYOFFSET); // 0xD3
+ ssd1306_command(0x0); // no offset
+ ssd1306_command(SSD1306_SETSTARTLINE | 0x0); // line #0
+ ssd1306_command(SSD1306_CHARGEPUMP); // 0x8D
+ ssd1306_command(vccstate==SSD1306_EXTERNALVCC?0x10:0x14);
+ ssd1306_command(SSD1306_MEMORYMODE); // 0x20
+ ssd1306_command(0x00); // 0x0 act like ks0108
+ ssd1306_command(SSD1306_SEGREMAP | 0x1);
+ ssd1306_command(SSD1306_COMSCANDEC);
+ ssd1306_command(SSD1306_SETCOMPINS); // 0xDA
+ ssd1306_command(ssd1306_lcdheight==32?0x02:0x12);
+ ssd1306_command(SSD1306_SETCONTRAST); // 0x81
+
+ if (ssd1306_lcdheight == 32)
+ ssd1306_command(0x8F);
+ else
+ ssd1306_command(vccstate==SSD1306_EXTERNALVCC?0x9F:0xCF);
+
+ ssd1306_command(SSD1306_SETPRECHARGE); // 0xd9
+ ssd1306_command(vccstate==SSD1306_EXTERNALVCC?0x22:0xF1);
+ ssd1306_command(SSD1306_SETVCOMDETECT); // 0xDB
+ ssd1306_command(0x40);
+ ssd1306_command(SSD1306_DISPLAYALLON_RESUME); // 0xA4
+ ssd1306_command(SSD1306_NORMALDISPLAY); // 0xA6
+ ssd1306_command(SSD1306_DISPLAYON);
+ }
else
- ssd1306_command(vccstate==SSD1306_EXTERNALVCC?0x9F:0xCF);
-
- ssd1306_command(SSD1306_SETPRECHARGE); // 0xd9
- ssd1306_command(vccstate==SSD1306_EXTERNALVCC?0x22:0xF1);
- ssd1306_command(SSD1306_SETVCOMDETECT); // 0xDB
- ssd1306_command(0x40);
- ssd1306_command(SSD1306_DISPLAYALLON_RESUME); // 0xA4
- ssd1306_command(SSD1306_NORMALDISPLAY); // 0xA6
- ssd1306_command(SSD1306_DISPLAYON); //--turn on oled panel
+ {
+ ssd1306_command(SSD1306_DISPLAYOFF); // 0xAE
+ ssd1306_command(SSD1306_SETDISPLAYCLOCKDIV, 0x80); // 0xD5 + the suggested ratio 0x80
+ ssd1306_command(SSD1306_SETMULTIPLEX, ssd1306_lcdheight==32?0x1F:0x3F); // 0xA8 +
+ ssd1306_command(SSD1306_SETDISPLAYOFFSET, 0x00); // 0xD3 + no offset
+ ssd1306_command(SSD1306_SETSTARTLINE | 0x0); // line #0
+ ssd1306_command(SSD1306_CHARGEPUMP, vccstate==SSD1306_EXTERNALVCC?0x10:0x14); // 0x8D
+ ssd1306_command(SSD1306_MEMORYMODE, 0x00); // 0x20 0x0 act like ks0108
+ ssd1306_command(SSD1306_SEGREMAP | 0x1);
+ ssd1306_command(SSD1306_COMSCANDEC);
+ ssd1306_command(SSD1306_SETCOMPINS, ssd1306_lcdheight==32?0x02:0x12); // 0xDA
+
+ if (ssd1306_lcdheight == 32)
+ ssd1306_command(SSD1306_SETCONTRAST, 0x8F);
+ else
+ ssd1306_command(SSD1306_SETCONTRAST, vccstate==SSD1306_EXTERNALVCC?0x9F:0xCF);
+
+ ssd1306_command(SSD1306_SETPRECHARGE, vccstate==SSD1306_EXTERNALVCC?0x22:0xF1); // 0xd9
+ ssd1306_command(SSD1306_SETVCOMDETECT, 0x40); // 0xDB
+ ssd1306_command(SSD1306_DISPLAYALLON_RESUME); // 0xA4
+ ssd1306_command(SSD1306_NORMALDISPLAY); // 0xA6
+ ssd1306_command(0x21, 0x00, 0x7F); // Set column address; start 0, end 127
+ ssd1306_command(0x22, 0x00, 0x03); // Set row address; start 0, end 3
+ stopscroll();
+ ssd1306_command(SSD1306_DISPLAYON); //--turn on oled panel
+ }
+
}
@@ -309,14 +341,63 @@ void Adafruit_SSD1306::ssd1306_command(uint8_t c) {
{
// I2C
char buff[2] ;
- uint8_t control = 0x00; // Co = 0, D/C = 0
- buff[0] = control;
+ buff[0] = 0x00 ; // Co = 0, D/C = 0
buff[1] = c;
bcm2835_i2c_write(buff, sizeof(buff)) ;
}
}
+void Adafruit_SSD1306::ssd1306_command(uint8_t c0, uint8_t c1)
+{
+ char buff[3] ;
+ buff[1] = c0;
+ buff[2] = c1;
+
+ // Is SPI
+ if (isSPI())
+ {
+ // Setup D/C line to low
+ bcm2835_gpio_write(dc, LOW);
+
+ // Write Data
+ fastSPIwrite(&buff[1], 2);
+ }
+ else
+ {
+ // I2C
+ buff[0] = 0x00 ; // Co = 0, D/C = 0
+ bcm2835_i2c_write(buff, 3) ;
+ }
+}
+
+void Adafruit_SSD1306::ssd1306_command(uint8_t c0, uint8_t c1, uint8_t c2)
+{
+ char buff[4] ;
+
+ buff[1] = c0;
+ buff[2] = c1;
+ buff[3] = c2;
+
+ // Is SPI
+ if (isSPI())
+ {
+ // SPI
+ // Setup D/C line to low
+ bcm2835_gpio_write(dc, LOW);
+
+ // Write Data
+ fastSPIwrite(&buff[1], 3);
+ }
+ else
+ {
+ // I2C
+ buff[0] = 0x00; // Co = 0, D/C = 0;
+ bcm2835_i2c_write(buff, sizeof(buff)) ;
+ }
+}
+
+
// startscrollright
// Activate a right handed scroll for rows start through stop
// Hint, the display is 16 rows tall. To scroll the whole display, run:
@@ -409,10 +490,13 @@ void Adafruit_SSD1306::ssd1306_data(uint8_t c) {
}
}
-void Adafruit_SSD1306::display(void) {
- ssd1306_command(SSD1306_SETLOWCOLUMN | 0x0); // low col = 0
- ssd1306_command(SSD1306_SETHIGHCOLUMN | 0x0); // hi col = 0
- ssd1306_command(SSD1306_SETSTARTLINE | 0x0); // line #0
+void Adafruit_SSD1306::display(void)
+{
+ ssd1306_command(SSD1306_SETLOWCOLUMN | 0x0); // low col = 0
+ ssd1306_command(SSD1306_SETHIGHCOLUMN | 0x0); // hi col = 0
+ ssd1306_command(SSD1306_SETSTARTLINE | 0x0); // line #0
+
+ uint16_t i=0 ;
// SPI
if ( isSPI())
@@ -420,7 +504,7 @@ void Adafruit_SSD1306::display(void) {
// set D/C line to High
bcm2835_gpio_write(dc, HIGH);
- for (uint16_t i=0; i<(ssd1306_lcdwidth*ssd1306_lcdheight/8); i++)
+ for ( i=0; i<(ssd1306_lcdwidth*ssd1306_lcdheight/8); i++)
{
fastSPIwrite(buffer[i]);
}
@@ -434,45 +518,23 @@ void Adafruit_SSD1306::display(void) {
}
}
}
+ // I2C
else
{
- char buff[1] ;
+ char buff[17] ;
+ uint8_t x ;
- // I2C
- for (uint16_t i=0; i<(ssd1306_lcdwidth*ssd1306_lcdheight/8); i++)
+ /// loop trought all buffer
+ for ( i=0; i<(ssd1306_lcdwidth*ssd1306_lcdheight/8); i++ )
{
- buff[0] = 0x40;
- bcm2835_i2c_write ( buff, sizeof(buff)) ;
-
- // send a bunch of data in one xmission
- // may be a bcm2835_i2c_write ( buffer, 16);
- // could work, I do not have LCD to test
- for (uint8_t x=0; x<16; x++)
- {
- //Wire.write(buffer[i]);
- buff[0] = buffer[i];
- bcm2835_i2c_write ( buff, sizeof(buff));
- i++;
- }
- i--;
- }
- // i wonder why we have to do this (check datasheet)
- if (ssd1306_lcdheight == 32)
- {
- for (uint16_t i=0; i<(ssd1306_lcdwidth*ssd1306_lcdheight/8); i++)
- {
- // send a bunch of data in one xmission
- buff[0] = 0x40;
- bcm2835_i2c_write ( buff, sizeof(buff)) ;
-
- buff[0] = 0x00;
- for (uint8_t x=0; x<16; x++)
- {
- bcm2835_i2c_write ( buff, sizeof(buff)) ;
- i++;
- }
- i--;
- }
+ buff[0] = 0x40; // Co = 0; D/C# = 1 for data
+
+ // send a bunch of 16 data byte in one xmission
+ for (x=0; x<16; x++)
+ buff[x+1] = buffer[i++];
+
+ bcm2835_i2c_write ( buff, sizeof(buff));
+ i--;
}
}
}
@@ -488,4 +550,8 @@ inline void Adafruit_SSD1306::fastSPIwrite(uint8_t d) {
bcm2835_spi_transfer(d);
}
+inline void Adafruit_SSD1306::fastSPIwrite(char* tbuf, uint32_t len) {
+
+ bcm2835_spi_writenb(tbuf, len);
+}
View
3  Adafruit_SSD1306.h
@@ -96,6 +96,8 @@ class Adafruit_SSD1306 : public Adafruit_GFX {
void begin(uint8_t switchvcc = SSD1306_SWITCHCAPVCC, uint8_t i2caddr = SSD1306_I2C_ADDRESS);
void ssd1306_command(uint8_t c);
+ void ssd1306_command(uint8_t c0, uint8_t c1);
+ void ssd1306_command(uint8_t c0, uint8_t c1, uint8_t c2);
void ssd1306_data(uint8_t c);
void clearDisplay(void);
@@ -118,6 +120,7 @@ class Adafruit_SSD1306 : public Adafruit_GFX {
int8_t _i2caddr, dc, rst, cs;
int16_t ssd1306_lcdwidth, ssd1306_lcdheight;
void fastSPIwrite(uint8_t c);
+ void fastSPIwrite(char* tbuf, uint32_t len);
void slowSPIwrite(uint8_t c);
volatile uint8_t *dcport;
View
2  ArduiPi_SSD1306.h
@@ -28,7 +28,7 @@
#define OLED_SPI_CS0 BCM2835_SPI_CS0 /* Chip Select CE0 */
#define OLED_SPI_CS1 BCM2835_SPI_CS1 /* Chip Select CE1 */
#define OLED_SPI_CS BCM2835_SPI_CS1 /* Default Chip Select */
-#define OLED_I2C_RESET 4
+#define OLED_I2C_RESET RPI_V2_GPIO_P1_22 /* GPIO 25 pin 12 */
// Arduino Compatible type
typedef uint8_t boolean;
View
298 bcm2835.c
@@ -18,16 +18,18 @@
// 06/29/2013 Incorporated latest version of bcm2825.h done by Mike McCauley
-#include <stdlib.h>
#include <stdio.h>
-#include <errno.h>
+#include <stdlib.h>
#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/i2c-dev.h>
+
+#include <errno.h>
#include <sys/mman.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
-
#include "bcm2835.h"
// This define enables a little test program (by default a blinking output on pin RPI_GPIO_PIN_11)
@@ -55,6 +57,9 @@ static uint8_t debug = 0;
// I2C The time needed to transmit one byte. In microseconds.
static int i2c_byte_wait_us = 0;
+// i2c file descriptor for opeping i2c device
+static int i2c_fd = 0;
+
// SPI Custom Chip Select Pin
static int spi_custom_cs = 0;
@@ -803,270 +808,83 @@ void bcm2835_spi_setChipSelectPolarity(uint8_t cs, uint8_t active)
}
}
-void bcm2835_i2c_begin(void)
+int bcm2835_i2c_begin(void)
{
- volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_DIV/4;
-
- // Set the I2C/BSC1 pins to the Alt 0 function to enable I2C access on them
- bcm2835_gpio_fsel(RPI_V2_GPIO_P1_03, BCM2835_GPIO_FSEL_ALT0); // SDA
- bcm2835_gpio_fsel(RPI_V2_GPIO_P1_05, BCM2835_GPIO_FSEL_ALT0); // SCL
-
- // Read the clock divider register
- uint16_t cdiv = bcm2835_peri_read(paddr);
- // Calculate time for transmitting one byte
- // 1000000 = micros seconds in a second
- // 9 = Clocks per byte : 8 bits + ACK
- i2c_byte_wait_us = ((float)cdiv / BCM2835_CORE_CLK_HZ) * 1000000 * 9;
-}
+ int fd ;
-void bcm2835_i2c_end(void)
-{
- // Set all the I2C/BSC1 pins back to input
- bcm2835_gpio_fsel(RPI_V2_GPIO_P1_03, BCM2835_GPIO_FSEL_INPT); // SDA
- bcm2835_gpio_fsel(RPI_V2_GPIO_P1_05, BCM2835_GPIO_FSEL_INPT); // SCL
+ if ((fd = open (bcm2835_get_pi_version() == 1 ? "/dev/i2c-0":"/dev/i2c-1" , O_RDWR)) < 0)
+ return fd;
+
+ // Set i2c descriptor
+ i2c_fd = fd;
+
+ return i2c_fd ;
+
}
-void bcm2835_i2c_setSlaveAddress(uint8_t addr)
+void bcm2835_i2c_end(void)
{
- // Set I2C Device Address
- volatile uint32_t* paddr = bcm2835_bsc1 + BCM2835_BSC_A/4;
- bcm2835_peri_write(paddr, addr);
+ // close i2c bus
+ if ( i2c_fd )
+ {
+ close(i2c_fd);
+ i2c_fd = 0;
+ }
}
-// 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)
+int bcm2835_i2c_setSlaveAddress(uint8_t addr)
{
- 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;
-}
+ if (!i2c_fd)
+ return (-1);
+ // Set I2C Device Address
+ return (ioctl (i2c_fd, I2C_SLAVE, 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_i2c_setClockDivider( (uint16_t)divider );
+
+ bcm2835_peri_write(paddr, divider);
}
// Writes an number of bytes to I2C
-uint8_t bcm2835_i2c_write(const char * buf, uint32_t len)
+int bcm2835_i2c_write(const char * buf, uint32_t len)
{
- 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;
-
- 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_nb(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE);
- // Set Data Length
- bcm2835_peri_write_nb(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_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST);
-
- // Transfer is over when BCM2835_BSC_S_DONE
- while(!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE ))
- {
- while ( remaining && (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_TXD ))
- {
- // Write to FIFO, no barrier
- bcm2835_peri_write_nb(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;
- }
+ int reason = -1 ;
+
+ if (!i2c_fd)
+ return (-1);
+
+ // Do simple use of I2C smbus command regarding number of bytes to transfer
+ // Write 1 byte
+ if (len == 2)
+ reason = i2c_smbus_write_byte_data(i2c_fd, buf[0], buf[1]);
+ // Write 1 word
+ else if (len == 3)
+ reason = i2c_smbus_write_word_data(i2c_fd, buf[0], (buf[2]<<8) | buf[1] );
+ // Write bulk data
+ else
+ reason = i2c_smbus_write_i2c_block_data(i2c_fd, buf[0], len-1, (const __u8 *) &buf[1]);
+
+ usleep(1);
- bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE);
+ return ( reason );
- return reason;
}
// Read an number of bytes from I2C
+// to do
uint8_t bcm2835_i2c_read(char* buf, uint32_t len)
{
- 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;
-
- 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_nb(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE);
- // Set Data Length
- bcm2835_peri_write_nb(dlen, len);
- // Start read
- bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ);
-
- // wait for transfer to complete
- while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE))
- {
- // we must empty the FIFO as it is populated and not use any delay
- while (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD)
- {
- // Read from FIFO, no barrier
- buf[i] = bcm2835_peri_read_nb(fifo);
- i++;
- remaining--;
- }
- }
-
- // transfer has finished - grab any remaining stuff in FIFO
- while (remaining && (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD))
- {
- // Read from FIFO, no barrier
- buf[i] = bcm2835_peri_read_nb(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 received
- else if (remaining)
- {
- reason = BCM2835_I2C_REASON_ERROR_DATA;
- }
-
- bcm2835_peri_set_bits(control, BCM2835_BSC_S_DONE , BCM2835_BSC_S_DONE);
-
- return reason;
-}
-
-// 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)
-{
- 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;
-
- 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_nb(status, BCM2835_BSC_S_CLKT | BCM2835_BSC_S_ERR | BCM2835_BSC_S_DONE);
- // Set Data Length
- bcm2835_peri_write_nb(dlen, 1);
- // Enable device and start transfer
- bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN);
- bcm2835_peri_write_nb(fifo, regaddr[0]);
- bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST);
-
- // poll for transfer has started
- while ( !( bcm2835_peri_read_nb(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_nb(dlen, len);
- bcm2835_peri_write_nb(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_nb(status) & BCM2835_BSC_S_DONE))
- {
- // we must empty the FIFO as it is populated and not use any delay
- while (remaining && bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD)
- {
- // Read from FIFO, no barrier
- buf[i] = bcm2835_peri_read_nb(fifo);
- i++;
- remaining--;
- }
- }
-
- // transfer has finished - grab any remaining stuff in FIFO
- while (remaining && (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD))
- {
- // Read from FIFO, no barrier
- buf[i] = bcm2835_peri_read_nb(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);
+ uint8_t reason = 0;
return reason;
}
View
28 bcm2835.h
@@ -1107,7 +1107,7 @@ extern "C" {
/// You should call bcm2835_i2c_end() when all I2C functions are complete to return the pins to
/// their default functions
/// \sa bcm2835_i2c_end()
- extern void bcm2835_i2c_begin(void);
+ extern int bcm2835_i2c_begin(void);
/// End I2C operations.
/// I2C pins P1-03 (SDA) and P1-05 (SCL)
@@ -1116,13 +1116,8 @@ extern "C" {
/// Sets the I2C slave address.
/// \param[in] addr The I2C slave address.
- extern void bcm2835_i2c_setSlaveAddress(uint8_t addr);
+ extern int bcm2835_i2c_setSlaveAddress(uint8_t addr);
- /// Sets the I2C clock divider and therefore the I2C clock speed.
- /// \param[in] divider The desired I2C clock divider, one of BCM2835_I2C_CLOCK_DIVIDER_*,
- /// see \ref bcm2835I2CClockDivider
- extern void bcm2835_i2c_setClockDivider(uint16_t divider);
-
/// Sets the I2C clock divider by converting the baudrate parameter to
/// the equivalent I2C clock divider. ( see \sa bcm2835_i2c_setClockDivider)
/// For the I2C standard 100khz you would set baudrate to 100000
@@ -1134,8 +1129,8 @@ extern "C" {
/// (as previously set by \sa bcm2835_i2c_setSlaveAddress)
/// \param[in] buf Buffer of bytes to send.
/// \param[in] len Number of bytes in the buf buffer, and the number of bytes to send.
- /// \return reason see \ref bcm2835I2CReasonCodes
- extern uint8_t bcm2835_i2c_write(const char * buf, uint32_t len);
+ /// \return i2c smbus command return code
+ extern int bcm2835_i2c_write(const char * buf, uint32_t len);
/// Transfers any number of bytes from the currently selected I2C slave.
/// (as previously set by \sa bcm2835_i2c_setSlaveAddress)
@@ -1144,21 +1139,6 @@ extern "C" {
/// \return reason see \ref bcm2835I2CReasonCodes
extern uint8_t bcm2835_i2c_read(char* buf, uint32_t len);
- /// Allows reading from I2C slaves that require a repeated start (without any prior stop)
- /// to read after the required slave register has been set. For example, the popular
- /// MPL3115A2 pressure and temperature sensor. Note that your device must support or
- /// require this mode. If your device does not require this mode then the standard
- /// combined:
- /// \sa bcm2835_i2c_write
- /// \sa bcm2835_i2c_read
- /// are a better choice.
- /// Will read from the slave previously set by \sa bcm2835_i2c_setSlaveAddress
- /// \param[in] regaddr Buffer containing the slave register you wish to read from.
- /// \param[in] buf Buffer of bytes to receive.
- /// \param[in] len Number of bytes in the buf buffer, and the number of bytes to received.
- /// \return reason see \ref bcm2835I2CReasonCodes
- extern uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len);
-
/// @}
/// \defgroup st System Timer access
Please sign in to comment.
Something went wrong with that request. Please try again.