diff --git a/firmware/drivers/fmradio_i2c.c b/firmware/drivers/fmradio_i2c.c index 1c9bc300c2..0a1d0c1fd7 100644 --- a/firmware/drivers/fmradio_i2c.c +++ b/firmware/drivers/fmradio_i2c.c @@ -80,7 +80,17 @@ int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count) #endif /* delay loop to achieve 400kHz at 120MHz CPU frequency */ -#define DELAY do { volatile int _x; for(_x=0;_x<22;_x++);} while (0) +#define DELAY \ + ({ \ + int _x_; \ + asm volatile ( \ + "move.l #21, %[_x_] \r\n" \ + "1: \r\n" \ + "subq.l #1, %[_x_] \r\n" \ + "bhi.b 1b \r\n" \ + : [_x_]"=&d"(_x_) \ + ); \ + }) static void fmradio_i2c_start(void) { @@ -102,8 +112,8 @@ static void fmradio_i2c_stop(void) SDA_HI; } - -static void fmradio_i2c_ack(void) +/* Generate ACK or NACK */ +static void fmradio_i2c_ack(bool nack) { /* Here's the deal. The slave is slow, and sometimes needs to wait before it can receive the acknowledge. Therefore it forces the clock @@ -114,7 +124,11 @@ static void fmradio_i2c_ack(void) we have to drive the SCL high repeatedly to simulate a pullup. */ SCL_LO; /* Set the clock low */ - SDA_LO; + + if (nack) + SDA_HI; + else + SDA_LO; SCL_INPUT; /* Set the clock to input */ while(!SCL) /* and wait for the slave to release it */ @@ -248,8 +262,7 @@ int fmradio_i2c_read(int address, unsigned char* buf, int count) for (i=count; i>0; i--) { *buf++ = fmradio_i2c_inb(); - if (i != 1) - fmradio_i2c_ack(); + fmradio_i2c_ack(i == 1); } } else @@ -275,7 +288,7 @@ int fmradio_i2c_read(int address, unsigned char* buf, int count) #define SCL (PBDR & 0x0002) /* arbitrary delay loop */ -#define DELAY do { volatile int _x; for(_x=0;_x<20;_x++);} while (0) +#define DELAY do { int _x; for(_x=0;_x<20;_x++);} while (0) static void fmradio_i2c_start(void) { @@ -296,7 +309,7 @@ static void fmradio_i2c_stop(void) } -static void fmradio_i2c_ack(void) +static void fmradio_i2c_ack(bool nack) { /* Here's the deal. The slave is slow, and sometimes needs to wait before it can receive the acknowledge. Therefore it forces the clock @@ -304,7 +317,11 @@ static void fmradio_i2c_ack(void) high before we release the ack. */ SCL_LO; /* Set the clock low */ - SDA_LO; + + if (nack) + SDA_HI; + else + SDA_LO; SCL_INPUT; /* Set the clock to input */ while(!SCL) /* and wait for the slave to release it */ @@ -416,8 +433,7 @@ int fmradio_i2c_read(int address, unsigned char* buf, int count) for (i=count; i>0; i--) { *buf++ = fmradio_i2c_inb(); - if (i != 1) - fmradio_i2c_ack(); + fmradio_i2c_ack(i == 1); } } else diff --git a/firmware/target/coldfire/iriver/h100/adc-h100.c b/firmware/target/coldfire/iriver/h100/adc-h100.c index a20b1e8d30..fb5afce9f5 100644 --- a/firmware/target/coldfire/iriver/h100/adc-h100.c +++ b/firmware/target/coldfire/iriver/h100/adc-h100.c @@ -34,7 +34,17 @@ static unsigned char adcdata[NUM_ADC_CHANNELS]; #define DI_HI or_l(0x00200000, &GPIO_OUT) /* delay loop */ -#define DELAY do { int _x; for(_x=0;_x<10;_x++) asm volatile ("");} while (0) +#define DELAY \ + ({ \ + int _x_; \ + asm volatile ( \ + "move.l #9, %[_x_] \r\n" \ + "1: \r\n" \ + "subq.l #1, %[_x_] \r\n" \ + "bhi.b 1b \r\n" \ + : [_x_]"=&d"(_x_) \ + ); \ + }) unsigned short adc_scan(int channel) { diff --git a/firmware/target/coldfire/iriver/h100/sw_i2c-h100.c b/firmware/target/coldfire/iriver/h100/sw_i2c-h100.c index 49db2b621d..3b2cdc4042 100644 --- a/firmware/target/coldfire/iriver/h100/sw_i2c-h100.c +++ b/firmware/target/coldfire/iriver/h100/sw_i2c-h100.c @@ -42,7 +42,17 @@ #define SDA_HI and_l(~0x00002000, &GPIO1_ENABLE) /* delay loop to achieve 400kHz at 120MHz CPU frequency */ -#define DELAY do { volatile int _x; for(_x=0;_x<22;_x++);} while(0) +#define DELAY \ + ({ \ + int _x_; \ + asm volatile ( \ + "move.l #21, %[_x_] \r\n" \ + "1: \r\n" \ + "subq.l #1, %[_x_] \r\n" \ + "bhi.b 1b \r\n" \ + : [_x_]"=&d"(_x_) \ + ); \ + }) void sw_i2c_init(void) {