/* twi_master.c */ #include "twi_master.h" #include #include #include #include #include #define NB_ITER_WAIT 40000 #define NB_RETRY 5 static uint8_t buffer[TWI_BUF_SIZE]; static uint8_t twi_dest_addr; static uint8_t twi_len; static uint8_t twi_idx; static uint8_t twi_nb_retry; uint8_t twi_state = 0; #define SYSCLK 14745600UL /* compteur 10 ms pour attente du bus 40 000 iterations */ /* compteur x essais y ms secondes d'attende */ void twi_master_init (void) { /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */ #if defined(TWPS0) TWSR = 0; #endif TWBR = (SYSCLK / 100000UL - 16) / 2; TWCR = _BV (TWEN) | _BV (TWIE); } int8_t twi_master_send (uint8_t addr, uint8_t data[], uint8_t len) { rs232_putc ('a'); twi_state = 0; twi_nb_retry = 0; if (len > TWI_BUF_SIZE) return -1; twi_dest_addr = addr & 0xfe; twi_len = len; memcpy (buffer, data, len); /* envoie du start */ TWCR |= _BV(TWSTA); TWCR |= _BV(TWINT); rs232_putc ('b'); while (!twi_state) ; rs232_putc ('c'); return twi_state; } int8_t twi_master_read (uint8_t addr, uint8_t data[], uint8_t len) { rs232_putc ('a'); twi_state = 0; twi_nb_retry = 0; if (len > TWI_BUF_SIZE) return -1; twi_dest_addr = addr | 0x01; twi_len = len; //TWCR &= ~_BV (TWSTO); TWCR |= _BV(TWSTA) | _BV (TWINT); rs232_putc ('z'); while (!twi_state) ; rs232_putc ('x'); memcpy (data, buffer, len); rs232_putc ('w'); return twi_state; } SIGNAL (SIG_2WIRE_SERIAL) { rs232_putc ('y'); switch (TW_STATUS) { /* Master */ case TW_START: case TW_REP_START: /* start transmis, on envoie l'adresse */ rs232_putc ('d'); TWCR &= ~ (_BV (TWSTA) | _BV (TWSTO) | _BV (TWINT)); TWDR = twi_dest_addr; twi_idx = 0; break; case TW_MT_ARB_LOST: /* valable pour le receiver aussi */ /* todo */ rs232_putc ('e'); break; /* Master Transmitter */ case TW_MT_DATA_ACK: case TW_MT_SLA_ACK: /* slave ok * On envoi des données si il en reste */ if (twi_idx < twi_len) { rs232_putc ('f'); TWDR = buffer[twi_idx ++]; } else { TWCR |= _BV (TWSTO); rs232_putc ('g'); twi_state = 1; } break; case TW_MT_SLA_NACK: /* le slave ne repond plus * on essaye NB_RETRY avant d'arreter */ if (twi_nb_retry < NB_RETRY) { rs232_putc ('h'); TWCR |= _BV (TWSTA); twi_nb_retry ++; } else { rs232_putc ('i'); TWCR |= _BV (TWSTO); twi_state = 2; } break; case TW_MT_DATA_NACK: /* le slave ne veut plus de donnée */ rs232_putc ('j'); TWCR |= _BV (TWSTO); twi_state = 1; break; /* Master Receiver */ case TW_MR_SLA_ACK: rs232_putc ('p'); if (twi_len > 1) /* on recoit plusieurs octet */ { rs232_putc ('k'); TWCR |= _BV (TWEA); } break; case TW_MR_SLA_NACK: if (twi_nb_retry < NB_RETRY) { rs232_putc ('l'); TWCR |= _BV (TWEA); } else { rs232_putc ('m'); TWCR |= _BV (TWSTO); twi_state = -2; } break; case TW_MR_DATA_ACK: buffer[twi_idx ++] = TWDR; rs232_putc ('n'); if (twi_idx == (twi_len - 1)) TWCR |= _BV (TWEA); break; case TW_MR_DATA_NACK: /* dernier byte */ twi_state = 1; rs232_putc ('o'); buffer[twi_idx ++] = TWDR; TWCR |= _BV (TWSTO); break; } TWCR |= _BV (TWINT); }