I2C: remove parameter 'address' from i2c_write().

As we usually talk to one device only, there's not much point in
carrying around the address all the time. Surprise, this saves
only 16 bytes binary size despite of heavy usage.
This commit is contained in:
Markus Hitter 2016-04-05 20:45:03 +02:00
parent 55be863b84
commit 8e8946dd37
4 changed files with 37 additions and 30 deletions

27
i2c.c
View File

@ -108,9 +108,23 @@ volatile uint8_t sendbuf[BUFSIZE];
\param address Address the system should listen to in slave mode, unused \param address Address the system should listen to in slave mode, unused
when configured for master mode. In master mode, receiver when configured for master mode. In master mode, receiver
address is given to the send command. address is given to the send command.
This also sets the I2C address. In slave mode it's the address we listen on.
In master mode it's the communication target address. As master one can talk
to different devices. Call again i2c_init() for changing the target address,
then. Doing so won't interrupt ongoing transmissions and overhead is small.
*/ */
void i2c_init(uint8_t address) { void i2c_init(uint8_t address) {
// In case this is a re-inititalisation,
// don't interrupt an ongoing transmission.
while (i2c_state & I2C_MODE_BUSY) {
delay_us(10);
}
i2c_address = address;
#ifdef I2C_MASTER_MODE #ifdef I2C_MASTER_MODE
#ifdef I2C_ENABLE_PULLUPS #ifdef I2C_ENABLE_PULLUPS
SET_INPUT(SCL); SET_INPUT(SCL);
@ -135,7 +149,6 @@ void i2c_init(uint8_t address) {
#endif /* I2C_MASTER_MODE */ #endif /* I2C_MASTER_MODE */
#ifdef I2C_SLAVE_MODE #ifdef I2C_SLAVE_MODE
i2c_address = address;
TWAR = i2c_address; // We listen to broadcasts if lowest bit is set. TWAR = i2c_address; // We listen to broadcasts if lowest bit is set.
TWCR = (0<<TWINT)|(0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN)|(1<<TWIE); TWCR = (0<<TWINT)|(0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEN)|(1<<TWIE);
#endif #endif
@ -158,12 +171,13 @@ uint8_t i2c_busy(void) {
/** /**
Send a byte to the I2C partner. Send a byte to the I2C partner.
\param address I2C address of the communications partner.
\param data The byte to be buffered/sent. \param data The byte to be buffered/sent.
\param last_byte Wether this is the last byte of a transmission. \param last_byte Wether this is the last byte of a transmission.
This implementation assumes to talk to mostly one communications client. To
set the target, or to change it between transmissions, call i2c_init().
Unlike many other protocols (serial, SPI), I2C has an explicite transmission Unlike many other protocols (serial, SPI), I2C has an explicite transmission
start and transmission end. Invoking code has to tell wether the given byte start and transmission end. Invoking code has to tell wether the given byte
is the last byte of a transmission, so sending code can properly end it. is the last byte of a transmission, so sending code can properly end it.
@ -187,7 +201,7 @@ uint8_t i2c_busy(void) {
limitation is, one can end a transmisson by simply not writing for a while, limitation is, one can end a transmisson by simply not writing for a while,
until it's sure the buffer became empty. until it's sure the buffer became empty.
*/ */
void i2c_write(uint8_t address, uint8_t data, uint8_t last_byte) { void i2c_write(uint8_t data, uint8_t last_byte) {
while (i2c_should_end || ! buf_canwrite(send)) { while (i2c_should_end || ! buf_canwrite(send)) {
delay_us(10); delay_us(10);
@ -195,12 +209,7 @@ void i2c_write(uint8_t address, uint8_t data, uint8_t last_byte) {
if (i2c_state & I2C_MODE_FREE) { if (i2c_state & I2C_MODE_FREE) {
// No transmission ongoing, start one. // No transmission ongoing, start one.
i2c_address = address;
// Just send.
i2c_state = I2C_MODE_SAWP; i2c_state = I2C_MODE_SAWP;
// Start transmission.
TWCR = (1<<TWINT)|(0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)|(1<<TWEN)|(1<<TWIE); TWCR = (1<<TWINT)|(0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)|(1<<TWEN)|(1<<TWIE);
i2c_state |= I2C_MODE_BUSY; i2c_state |= I2C_MODE_BUSY;
} }

2
i2c.h
View File

@ -40,7 +40,7 @@
void i2c_init(uint8_t address); void i2c_init(uint8_t address);
uint8_t i2c_busy(void); uint8_t i2c_busy(void);
void i2c_write(uint8_t address, uint8_t data, uint8_t last_byte); void i2c_write(uint8_t data, uint8_t last_byte);
#endif /* I2C */ #endif /* I2C */

View File

@ -162,8 +162,7 @@ static void i2c_test(void) {
for (i = 0; i < sizeof(display_init); i++) { for (i = 0; i < sizeof(display_init); i++) {
// Send last byte with 'last_byte' set. // Send last byte with 'last_byte' set.
i2c_write(DISPLAY_I2C_ADDRESS, pgm_read_byte(&display_init[i]), i2c_write(pgm_read_byte(&display_init[i]), (i == sizeof(display_init) - 1));
(i == sizeof(display_init) - 1));
} }
/** /**
@ -172,20 +171,20 @@ static void i2c_test(void) {
zeros, byte by byte. zeros, byte by byte.
*/ */
// Set horizontal adressing mode. // Set horizontal adressing mode.
i2c_write(DISPLAY_I2C_ADDRESS, 0x00, 0); i2c_write(0x00, 0);
i2c_write(DISPLAY_I2C_ADDRESS, 0x20, 0); i2c_write(0x20, 0);
i2c_write(DISPLAY_I2C_ADDRESS, 0x00, 1); i2c_write(0x00, 1);
// Write 512 zeros. // Write 512 zeros.
i2c_write(DISPLAY_I2C_ADDRESS, 0x40, 0); i2c_write(0x40, 0);
for (i = 0; i < 512; i++) { for (i = 0; i < 512; i++) {
i2c_write(DISPLAY_I2C_ADDRESS, 0x00, (i == 511)); i2c_write(0x00, (i == 511));
} }
// Return to page adressing mode. // Return to page adressing mode.
i2c_write(DISPLAY_I2C_ADDRESS, 0x00, 0); i2c_write(0x00, 0);
i2c_write(DISPLAY_I2C_ADDRESS, 0x20, 0); i2c_write(0x20, 0);
i2c_write(DISPLAY_I2C_ADDRESS, 0x02, 1); i2c_write(0x02, 1);
/** /**
Setup cursor on display. Setup cursor on display.
@ -193,32 +192,31 @@ static void i2c_test(void) {
"Welcome to Teacup" is 64 pixel columns wide, entire display is "Welcome to Teacup" is 64 pixel columns wide, entire display is
128 columns, so we offset by 32 columns to get it to the center. 128 columns, so we offset by 32 columns to get it to the center.
*/ */
i2c_write(DISPLAY_I2C_ADDRESS, 0x00, 0); i2c_write(0x00, 0);
// Line 1. // Line 1.
i2c_write(DISPLAY_I2C_ADDRESS, 0xB0 | 1, 0); i2c_write(0xB0 | 1, 0);
// Column 32. // Column 32.
i2c_write(DISPLAY_I2C_ADDRESS, 0x00 | (32 & 0x0F), 0); i2c_write(0x00 | (32 & 0x0F), 0);
i2c_write(DISPLAY_I2C_ADDRESS, 0x10 | ((32 >> 4) & 0x0F), 1); i2c_write(0x10 | ((32 >> 4) & 0x0F), 1);
// Render text to bitmap to display. // Render text to bitmap to display.
i2c_write(DISPLAY_I2C_ADDRESS, 0x40, 0); i2c_write(0x40, 0);
while (*message) { while (*message) {
uint8_t index = (uint8_t)*message - 0x20; uint8_t index = (uint8_t)*message - 0x20;
// Send the character bitmap. // Send the character bitmap.
for (i = 0; i < pgm_read_byte(&font_8x4[index].columns); i++) { for (i = 0; i < pgm_read_byte(&font_8x4[index].columns); i++) {
i2c_write(DISPLAY_I2C_ADDRESS, i2c_write(pgm_read_byte(&font_8x4[index].data[i]), 0);
pgm_read_byte(&font_8x4[index].data[i]), 0);
} }
// Send space between characters. // Send space between characters.
for (i = 0; i < FONT_SYMBOLS_SPACE; i++) { for (i = 0; i < FONT_SYMBOLS_SPACE; i++) {
i2c_write(DISPLAY_I2C_ADDRESS, 0x00, 0); i2c_write(0x00, 0);
} }
message++; message++;
} }
// Send another space for transmission end. // Send another space for transmission end.
i2c_write(DISPLAY_I2C_ADDRESS, 0x00, 1); i2c_write(0x00, 1);
} }
#endif /* I2C_TEST */ #endif /* I2C_TEST */

View File

@ -96,7 +96,7 @@ void init(void) {
#endif #endif
#ifdef I2C #ifdef I2C
i2c_init(0); i2c_init(DISPLAY_I2C_ADDRESS);
#endif #endif
// set up timers // set up timers