]> cloudbase.mooo.com Git - z180-stamp.git/blobdiff - avr/i2c.c
User Timer0 as Z180 Clock
[z180-stamp.git] / avr / i2c.c
index df97fea36da267a86d853310f67052fdbd9760e5..dbb5da15e19ec122e69bba24894d1f3e2710cfbd 100644 (file)
--- a/avr/i2c.c
+++ b/avr/i2c.c
 #include "debug.h"
 #include "i2c.h"
 
-#ifdef DEBUG
-//# define DEBUG_I2C
-#endif
+#define  DEBUG_I2C 0
+
+#define debug_i2c(fmt, args...)                        \
+       debug_cond(DEBUG_I2C, fmt, ##args)
+
 
 /* General TWI Master status codes */
 #define TWI_START                  0x08  /* START has been transmitted */
        uint8_t buf[CONFIG_SYS_I2C_BUFSIZE];
 } i2c_msg_t;
 
-static i2c_msg_t xmit;
+static volatile i2c_msg_t xmit;
 
 ISR(TWI_vect)
 {
-       uint8_t next_twcr;
+       uint8_t tmp_stat;
        uint8_t tmp_idx;
+       uint8_t next_twcr;
+       uint8_t n;
+
+       tmp_idx = xmit.idx;
+       tmp_stat = xmit.stat;
 
        uint8_t twsr = TWSR;
                
@@ -112,98 +119,78 @@ ISR(TWI_vect)
 
        case TWI_START:
        case TWI_REP_START:
-               xmit.idx = 0;                   /* reset xmit_buf index */
-               xmit.stat = BUSY | START;
+               tmp_stat = BUSY | START;
+               tmp_idx = 0;                    /* reset xmit_buf index */
 
-               tmp_idx = xmit.idx;
                if (tmp_idx < xmit.len) {               /* all bytes transmited? */
                        TWDR = xmit.buf[tmp_idx];
-                       xmit.idx = ++tmp_idx;
+                       ++tmp_idx;
                        next_twcr = (1<<TWEN)|(1<<TWIE)|(1<<TWINT);
                } else {
-                       xmit.stat |= XMIT_DONE;
-                       xmit.stat &= ~BUSY;
+                       tmp_stat |= XMIT_DONE;
+                       tmp_stat &= ~BUSY;
                        next_twcr = (1<<TWEN)|(0<<TWIE)|(1<<TWINT)|(1<<TWSTO);
                }
                break;
 
        case TWI_MTX_ADR_ACK:
-               xmit.stat |= ADDR_ACK;
-               
-               tmp_idx = xmit.idx;
-               if (tmp_idx < xmit.len) {               /* all bytes transmited? */
-                       TWDR = xmit.buf[tmp_idx];
-                       xmit.idx = ++tmp_idx;
-                       next_twcr = (1<<TWEN)|(1<<TWIE)|(1<<TWINT);
-               } else {
-                       xmit.stat |= XMIT_DONE;
-                       xmit.stat &= ~BUSY;
-                       next_twcr = (1<<TWEN)|(0<<TWIE)|(1<<TWINT)|(1<<TWSTO);
-               }
-               break;
-
        case TWI_MTX_DATA_ACK:
-               xmit.stat |= DATA_ACK;
+               if ((twsr&0xf8) == TWI_MTX_ADR_ACK)
+                       tmp_stat |= ADDR_ACK;
+               else
+                       tmp_stat |= DATA_ACK;
 
-               tmp_idx = xmit.idx;
                if (tmp_idx < xmit.len) {               /* all bytes transmited? */
                        TWDR = xmit.buf[tmp_idx];
-                       xmit.idx = ++tmp_idx;
+                       ++tmp_idx;
                        next_twcr = (1<<TWEN)|(1<<TWIE)|(1<<TWINT);
                } else {
-                       xmit.stat |= XMIT_DONE;
-                       xmit.stat &= ~BUSY;
+                       tmp_stat |= XMIT_DONE;
+                       tmp_stat &= ~BUSY;
                        next_twcr = (1<<TWEN)|(0<<TWIE)|(1<<TWINT)|(1<<TWSTO);
                }
-
                break;
 
        case TWI_MTX_DATA_NACK:
-               xmit.stat |= XMIT_DONE;
-               xmit.stat &= ~BUSY;
+               tmp_stat |= XMIT_DONE;
+               tmp_stat &= ~BUSY;
                next_twcr = (1<<TWEN)|(0<<TWIE)|(1<<TWINT)|(1<<TWSTO);
                break;
 
-       case TWI_MRX_ADR_ACK:
-               xmit.stat |= ADDR_ACK;
-               tmp_idx = xmit.idx;
-               if (tmp_idx < xmit.len-1) {
-                       next_twcr = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA);
-               } else {
-                       next_twcr = (1<<TWEN)|(1<<TWIE)|(1<<TWINT);
-               }
-               break;
-
        case TWI_MRX_DATA_ACK:
-               xmit.stat |= DATA_ACK;
-               tmp_idx = xmit.idx;
                xmit.buf[tmp_idx] = TWDR;
-               xmit.idx = ++tmp_idx;
-               if (tmp_idx < xmit.len-1) {
+               ++tmp_idx;
+               /* fall thru */
+       case TWI_MRX_ADR_ACK:
+               if ((twsr&0xf8) == TWI_MRX_ADR_ACK)
+                       tmp_stat |= ADDR_ACK;
+               else
+                       tmp_stat |= DATA_ACK;
+
+               n = xmit.len-1;
+               if (tmp_idx < n) {
                        next_twcr = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA);
                } else {
-               
                        next_twcr = (1<<TWEN)|(1<<TWIE)|(1<<TWINT);
                }
                break;
 
        case TWI_MRX_DATA_NACK:
-               xmit.stat |= ADDR_ACK | DATA_ACK;
+               tmp_stat |= ADDR_ACK | DATA_ACK;
 
-               tmp_idx = xmit.idx;
                xmit.buf[tmp_idx] = TWDR;
-               xmit.idx = ++tmp_idx;
+               ++tmp_idx;
                /* fall thru */
-
        default:
-               xmit.stat &= ~BUSY;
+               tmp_stat &= ~BUSY;
                next_twcr = (1<<TWEN)|(0<<TWIE)|(1<<TWINT)|(1<<TWSTO);
                break;
        }
 
-#ifdef DEBUG_I2C       
-       debug("|%02x", twsr);
-#endif
+       xmit.stat = tmp_stat;
+       xmit.idx = tmp_idx;
+
+       debug_i2c("|%02x", twsr);
        TWCR = next_twcr;
 }
 
@@ -217,32 +204,33 @@ static uint8_t twbr;
 static void _init(void)
 {
        xmit.stat = 0;
-#ifdef DEBUG_I2C
-       memset((void *) xmit.buf, 0xdf, sizeof(xmit.buf));
-#endif
 
        /* Disable TWI, disable TWI interrupt. */
        /* (Reset TWI hardware state machine.) */
        TWCR = TWI_C_DISABLE;
        _delay_us(5);
+#if DEBUG_I2C
+       memset((void *) xmit.buf, 0xdf, sizeof(xmit.buf));
+#endif
 
-       TWBR = twbr;
        TWDR = 0xff;
-       TWCR = TWI_C_ENABLE + twps;
+       TWBR = twbr;
+       TWSR = twps & 0x03;
+       TWCR = TWI_C_ENABLE;
 }
 
 void i2c_init(uint32_t speed)
 {
        twps = 0;
-       uint32_t tmptwbr = F_CPU /2 / speed - 8;
+       uint32_t tmp_twbr = F_CPU /2 / speed - 8;
        
-       while (tmptwbr > 255) {
-               tmptwbr >>= 4;
+       while (tmp_twbr > 255) {
+               tmp_twbr >>= 4;
                twps += 1;
        }
-       debug_cond((twps > 3), "TWCLK too low: %lu Hz\n", speed);
+       debug_cond((twps > 3), "*** TWCLK too low: %lu Hz\n", speed);
 
-       twbr = (uint8_t) tmptwbr;
+       twbr = (uint8_t) tmp_twbr;
        _init();
 }
 
@@ -261,14 +249,14 @@ int_fast8_t i2c_waitready(void)
 
        xmit.stat |= timeout;
 
-#ifdef DEBUG_I2C
+#if DEBUG_I2C
        dump_ram((uint8_t *) &xmit, 4, "=== i2c_wait ready: (done)");
        _delay_ms(30);
 #endif 
        return xmit.stat;
 }
 
-//static
+static
 int i2c_send(uint8_t chip, uint16_t addr, uint8_t alen, uint8_t *buffer, int8_t len)
 {
        uint8_t i, n;
@@ -288,7 +276,7 @@ int i2c_send(uint8_t chip, uint16_t addr, uint8_t alen, uint8_t *buffer, int8_t
                xmit.buf[i] = *buffer++;
        xmit.len = i;
        
-#ifdef DEBUG_I2C
+#if DEBUG_I2C
        dump_ram((uint8_t *) &xmit, 0x20, "=== i2c_send");
        _delay_ms(30);
 #endif 
@@ -300,7 +288,7 @@ int i2c_send(uint8_t chip, uint16_t addr, uint8_t alen, uint8_t *buffer, int8_t
        return rc;
 }
 
-//static
+static
 int i2c_recv(uint8_t chip, uint8_t *buffer, int8_t len)
 {
        uint8_t rc;
@@ -313,7 +301,7 @@ int i2c_recv(uint8_t chip, uint8_t *buffer, int8_t len)
        xmit.len = len + 1;
        xmit.buf[0] = (chip<<1) | 1;
 
-#ifdef DEBUG_I2C
+#if DEBUG_I2C
        dump_ram((uint8_t *) &xmit, 0x20, "=== i2c_recv: before start");
        _delay_ms(30);
 #endif
@@ -321,7 +309,7 @@ int i2c_recv(uint8_t chip, uint8_t *buffer, int8_t len)
        TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA);
        rc = i2c_waitready();
 
-#ifdef DEBUG_I2C
+#if DEBUG_I2C
        dump_ram((uint8_t *) &xmit, 0x20, "=== i2c_recv: after completion");
        _delay_ms(30);
 #endif
@@ -360,7 +348,6 @@ int i2c_write(uint8_t chip, unsigned int addr, uint_fast8_t alen,
        
        i2c_send(chip, addr, alen, buffer, len);
        rc = i2c_waitready();
-       debug("** i2c_write: result=0x%02x\n",rc);
 
        return (rc & XMIT_DONE) != 0;
 }
@@ -380,7 +367,6 @@ int i2c_read(uint8_t chip, unsigned int addr, uint_fast8_t alen,
                i2c_send(chip, addr, alen, NULL, 0);
        }       
        rc = i2c_recv(chip, buffer, len);
-       debug("** i2c_read: result=0x%02x\n",rc);
 
        return !((rc & (XMIT_DONE|DATA_ACK)) == (XMIT_DONE|DATA_ACK));
 }