예제 #1
0
파일: avr_twi.c 프로젝트: Axbit/simavr
static avr_cycle_count_t
avr_twi_set_state_timer(
		struct avr_t * avr,
		avr_cycle_count_t when,
		void * param)
{
	avr_twi_t * p = (avr_twi_t *)param;
	_avr_twi_status_set(p, p->next_twstate, 1);
	p->next_twstate = 0;
	return 0;
}
예제 #2
0
파일: avr_twi.c 프로젝트: Axbit/simavr
static void
avr_twi_write(
		struct avr_t * avr,
		avr_io_addr_t addr,
		uint8_t v,
		void * param)
{
	avr_twi_t * p = (avr_twi_t *)param;

	uint8_t twen = avr_regbit_get(avr, p->twen);
	uint8_t twsta = avr_regbit_get(avr, p->twsta);
	uint8_t twsto = avr_regbit_get(avr, p->twsto);
	uint8_t twint = avr_regbit_get(avr, p->twi.raised);

	avr_core_watch_write(avr, addr, v);
#if AVR_TWI_DEBUG
	AVR_TRACE(avr, "%s %02x START:%d STOP:%d ACK:%d INT:%d TWSR:%02x (state %02x)\n",
			__func__, v,
			avr_regbit_get(avr, p->twsta),
			avr_regbit_get(avr, p->twsto),
			avr_regbit_get(avr, p->twea),
			avr_regbit_get(avr, p->twi.raised),
			avr_regbit_get_raw(p->io.avr, p->twsr), p->state);
#endif
	if (twen != avr_regbit_get(avr, p->twen)) {
		twen = !twen;
		if (!twen) { // if we were running, now now are not
			avr_regbit_clear(avr, p->twea);
			avr_regbit_clear(avr, p->twsta);
			avr_regbit_clear(avr, p->twsto);
			avr_clear_interrupt(avr, &p->twi);
			avr_core_watch_write(avr, p->r_twdr, 0xff);
			_avr_twi_status_set(p, TWI_NO_STATE, 0);
			p->state = 0;
			p->peer_addr = 0;
		}
		AVR_TRACE(avr, "TWEN: %d\n", twen);
		if (avr->data[p->r_twar]) {
			AVR_TRACE(avr, "TWEN Slave: %02x&%02x\n", avr->data[p->r_twar] >> 1, avr->data[p->r_twamr] >> 1);
			p->state |= TWI_COND_SLAVE;
		}
예제 #3
0
파일: avr_twi.c 프로젝트: jdpillon/simulide
static void
avr_twi_write(
		struct avr_t * avr,
		avr_io_addr_t addr,
		uint8_t v,
		void * param)
{
	avr_twi_t * p = (avr_twi_t *)param;

	uint8_t twen = avr_regbit_get(avr, p->twen);
	uint8_t twsta = avr_regbit_get(avr, p->twsta);
	uint8_t twsto = avr_regbit_get(avr, p->twsto);
	uint8_t twint = avr_regbit_get(avr, p->twi.raised);

	avr_core_watch_write(avr, addr, v);
#if AVR_TWI_DEBUG
	printf("avr_twi_write %02x START:%d STOP:%d ACK:%d INT:%d TWSR:%02x (state %02x)\n", v,
			avr_regbit_get(avr, p->twsta),
			avr_regbit_get(avr, p->twsto),
			avr_regbit_get(avr, p->twea),
			avr_regbit_get(avr, p->twi.raised),
			avr_regbit_get_raw(p->io.avr, p->twsr), p->state);
#endif
	if (twen != avr_regbit_get(avr, p->twen)) {
		twen = !twen;
		if (!twen) { // if we were running, now now are not
			avr_regbit_clear(avr, p->twea);
			avr_regbit_clear(avr, p->twsta);
			avr_regbit_clear(avr, p->twsto);
			avr_clear_interrupt(avr, &p->twi);
			avr_core_watch_write(avr, p->r_twdr, 0xff);
			_avr_twi_status_set(p, TWI_NO_STATE, 0);
			p->state = 0;
			p->peer_addr = 0;
		}
		printf("TWEN: %d\n", twen);
	}
	if (!twen)
		return;

	uint8_t cleared = avr_regbit_get(avr, p->twi.raised);

	/*int cleared = */avr_clear_interrupt_if(avr, &p->twi, twint);
//	printf("cleared %d\n", cleared);

	if (!twsto && avr_regbit_get(avr, p->twsto)) {
		// generate a stop condition
#if AVR_TWI_DEBUG
		printf("<<<<< I2C stop\n");
#endif
		if (p->state) { // doing stuff
			if (p->state & TWI_COND_START) {
				avr_raise_irq(p->io.irq + TWI_IRQ_MOSI,
						avr_twi_irq_msg(TWI_COND_STOP, p->peer_addr, 1));
			}
		}
		p->state = 0;
	}
	if (!twsta && avr_regbit_get(avr, p->twsta)) {
#if AVR_TWI_DEBUG
		printf(">>>>> I2C %sstart\n", p->state & TWI_COND_START ? "RE" : "");
#endif
		// generate a start condition
		if (p->state & TWI_COND_START)
			_avr_twi_delay_state(p, 3, TWI_REP_START);
		else
			_avr_twi_delay_state(p, 3, TWI_START);
		p->peer_addr = 0;
		p->state = TWI_COND_START;
	}

	if (cleared &&
			!avr_regbit_get(avr, p->twsta) &&
			!avr_regbit_get(avr, p->twsto)) {
		// writing or reading a byte
		if (p->state & TWI_COND_ADDR) {
			int do_read = p->peer_addr & 1;
#if AVR_TWI_DEBUG
			if (do_read)
				printf("I2C READ byte from %02x\n", p->peer_addr);
			else
				printf("I2C WRITE byte %02x to %02x\n", avr->data[p->r_twdr], p->peer_addr);
#endif
			// a normal data byte
			uint8_t msgv = do_read ? TWI_COND_READ : TWI_COND_WRITE;

			if (avr_regbit_get(avr, p->twea))
				msgv |= TWI_COND_ACK;

			p->state &= ~TWI_COND_ACK;	// clear ACK bit

			// if the latch is ready... as set by writing/reading the TWDR
			if ((p->state & msgv)) {

				// we send an IRQ and we /expect/ a slave to reply
				// immediately via an IRQ to set the COND_ACK bit
				// otherwise it's assumed it's been nacked...
				avr_raise_irq(p->io.irq + TWI_IRQ_MOSI,
						avr_twi_irq_msg(msgv, p->peer_addr, avr->data[p->r_twdr]));

				if (do_read) { // read ?
					_avr_twi_delay_state(p, 9,
							msgv & TWI_COND_ACK ?
									TWI_MRX_DATA_ACK : TWI_MRX_DATA_NACK);
				} else {
					_avr_twi_delay_state(p, 9,
							p->state & TWI_COND_ACK ?
									TWI_MTX_DATA_ACK : TWI_MTX_DATA_NACK);
				}
			}
#if AVR_TWI_DEBUG
			else
				printf("I2C latch is not ready, do nothing\n");
#endif
		} else {
#if AVR_TWI_DEBUG
			printf("I2C Master address %02x\n", avr->data[p->r_twdr]);
#endif
			// send the address
			p->state |= TWI_COND_ADDR;
			p->peer_addr = avr->data[p->r_twdr];
			p->state &= ~TWI_COND_ACK;	// clear ACK bit

			// we send an IRQ and we /expect/ a slave to reply
			// immediately via an IRQ tp set the COND_ACK bit
			// otherwise it's assumed it's been nacked...
			avr_raise_irq(p->io.irq + TWI_IRQ_MOSI,
					avr_twi_irq_msg(TWI_COND_START, p->peer_addr, 0));

			if (p->peer_addr & 1) { // read ?
				p->state |= TWI_COND_READ;	// always allow read to start with
				_avr_twi_delay_state(p, 9,
						p->state & TWI_COND_ACK ?
								TWI_MRX_ADR_ACK : TWI_MRX_ADR_NACK);
			} else {
				_avr_twi_delay_state(p, 9,
						p->state & TWI_COND_ACK ?
								TWI_MTX_ADR_ACK : TWI_MTX_ADR_NACK);
			}
		}
		p->state &= ~TWI_COND_WRITE;
	}
}