Exemplo n.º 1
0
static void avr_uart_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
{
	avr_uart_t * p = (avr_uart_t *)param;

	if (addr == p->r_udr) {
		avr_core_watch_write(avr, addr, v);

		if ( p->udrc.vector)
			avr_regbit_clear(avr, p->udrc.raised);
		avr_cycle_timer_register_usec(avr,
				p->usec_per_byte, avr_uart_txc_raise, p); // should be uart speed dependent

		if (p->flags & AVR_UART_FLAG_STDIO) {
			const int maxsize = 256;
			if (!p->stdio_out)
				p->stdio_out = malloc(maxsize);
			p->stdio_out[p->stdio_len++] = v < ' ' ? '.' : v;
			p->stdio_out[p->stdio_len] = 0;
			if (v == '\n' || p->stdio_len == maxsize) {
				p->stdio_len = 0;
				AVR_LOG(avr, LOG_TRACE, FONT_GREEN "%s\n" FONT_DEFAULT, p->stdio_out);
			}
		}
		TRACE(printf("UDR%c(%02x) = %02x\n", p->name, addr, v);)
		// tell other modules we are "outputting" a byte
		if (avr_regbit_get(avr, p->txen))
Exemplo n.º 2
0
static void avr_timer_tcnt_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
{
	avr_timer_t * p = (avr_timer_t *)param;
	avr_core_watch_write(avr, addr, v);
	uint16_t tcnt = _timer_get_tcnt(p);

	if (!p->tov_top)
		return;
		
	if (tcnt >= p->tov_top)
		tcnt = 0;
	
	// this involves some magicking
	// cancel the current timers, recalculate the "base" we should be at, reset the
	// timer base as it should, and re-schedule the timers using that base.
	
	avr_cycle_timer_cancel(avr, avr_timer_tov, p);
	avr_cycle_timer_cancel(avr, avr_timer_compa, p);
	avr_cycle_timer_cancel(avr, avr_timer_compb, p);
	avr_cycle_timer_cancel(avr, avr_timer_compc, p);

	uint64_t cycles = (tcnt * p->tov_cycles) / p->tov_top;

//	printf("%s-%c %d/%d -- cycles %d/%d\n", __FUNCTION__, p->name, tcnt, p->tov_top, (uint32_t)cycles, (uint32_t)p->tov_cycles);

	// this reset the timers bases to the new base
	if (p->tov_cycles > 1) {
		avr_cycle_timer_register(avr, p->tov_cycles - cycles, avr_timer_tov, p);
		p->tov_base = 0;
		avr_timer_tov(avr, avr->cycle - cycles, p);
	}

//	tcnt = ((avr->cycle - p->tov_base) * p->tov_top) / p->tov_cycles;
//	printf("%s-%c new tnt derive to %d\n", __FUNCTION__, p->name, tcnt);	
}
Exemplo n.º 3
0
/*
 * write to the TIFR register. Watch for code that writes "1" to clear
 * pending interrupts.
 */
static void
avr_timer_write_pending(
		struct avr_t * avr,
		avr_io_addr_t addr,
		uint8_t v,
		void * param)
{
	avr_timer_t * p = (avr_timer_t *)param;
	// save old bits values
	uint8_t ov = avr_regbit_get(avr, p->overflow.raised);
	uint8_t ic = avr_regbit_get(avr, p->icr.raised);
	uint8_t cp[AVR_TIMER_COMP_COUNT];

	for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++)
		cp[compi] = avr_regbit_get(avr, p->comp[compi].interrupt.raised);

	// write the value
	avr_core_watch_write(avr, addr, v);

	// clear any interrupts & flags
	avr_clear_interrupt_if(avr, &p->overflow, ov);
	avr_clear_interrupt_if(avr, &p->icr, ic);

	for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++)
		avr_clear_interrupt_if(avr, &p->comp[compi].interrupt, cp[compi]);
}
Exemplo n.º 4
0
static void
avr_usb_udcon_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
{
    avr_usb_t * p = (avr_usb_t *)param;

    if(avr->data[addr]&1 && !(v&1))
        avr_raise_irq(p->io.irq + USB_IRQ_ATTACH, !(v&1));
    avr_core_watch_write(avr, addr, v);
}
Exemplo n.º 5
0
static void avr_spi_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
{
    avr_spi_t * p = (avr_spi_t *)param;

    if (addr == p->r_spdr) {
        //	printf("avr_spi_write = %02x\n", v);
        avr_core_watch_write(avr, addr, v);
        avr_cycle_timer_register_usec(avr, 100, avr_spi_raise, p); // should be speed dependent
    }
}
Exemplo n.º 6
0
static void
avr_usb_uenum_write(
    struct avr_t * avr,
    avr_io_addr_t addr,
    uint8_t v,
    void * param)
{
    assert(v < num_endpoints);
    avr_core_watch_write(avr, addr, v);
}
Exemplo n.º 7
0
static void
avr_usb_udaddr_write(
    struct avr_t * avr,
    avr_io_addr_t addr,
    uint8_t v,
    void * param)
{
    if (v & 0x80)
        AVR_LOG(avr, LOG_TRACE, "USB: Activate address %d\n", v & 0x7f);
    avr_core_watch_write(avr, addr, v);
}
Exemplo n.º 8
0
static void
avr_usb_udaddr_write(
        struct avr_t * avr,
        avr_io_addr_t addr,
        uint8_t v,
        void * param)
{
	if (v & 0x80)
		printf("Activate address %d\n", v & 0x7f);
	avr_core_watch_write(avr, addr, v);
}
Exemplo n.º 9
0
static void avr_flash_write(avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
{
	avr_flash_t * p = (avr_flash_t *)param;

	avr_core_watch_write(avr, addr, v);

//	printf("** avr_flash_write %02x\n", v);

	if (avr_regbit_get(avr, p->selfprgen))
		avr_cycle_timer_register(avr, 4, avr_progen_clear, p); // 4 cycles is very little!
}
Exemplo n.º 10
0
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;
		}
Exemplo n.º 11
0
static void
avr_adc_write_adcsra(
		struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
{
	avr_adc_configure_trigger(avr, addr, v, param);
	
	avr_adc_t * p = (avr_adc_t *)param;
	uint8_t adsc = avr_regbit_get(avr, p->adsc);
	uint8_t aden = avr_regbit_get(avr, p->aden);

	avr->data[p->adsc.reg] = v;

	// can't write zero to adsc
	if (adsc && !avr_regbit_get(avr, p->adsc)) {
		avr_regbit_set(avr, p->adsc);
		v = avr->data[p->adsc.reg];
	}
	if (!aden && avr_regbit_get(avr, p->aden)) {
		// first conversion
		p->first = 1;
		AVR_LOG(avr, LOG_TRACE, "ADC: Start AREF %d AVCC %d\n", avr->aref, avr->avcc);
	}
	if (aden && !avr_regbit_get(avr, p->aden)) {
		// stop ADC
		avr_cycle_timer_cancel(avr, avr_adc_int_raise, p);
		avr_regbit_clear(avr, p->adsc);
		v = avr->data[p->adsc.reg];	// Peter Ross [email protected]
	}
	if (!adsc && avr_regbit_get(avr, p->adsc)) {
		// start one!
		uint8_t muxi = avr_regbit_get_array(avr, p->mux, ARRAY_SIZE(p->mux));
		union {
			avr_adc_mux_t mux;
			uint32_t v;
		} e = { .mux = p->muxmode[muxi] };
		avr_raise_irq(p->io.irq + ADC_IRQ_OUT_TRIGGER, e.v);

		// clock prescaler are just a bit shift.. and 0 means 1
		uint32_t div = avr_regbit_get_array(avr, p->adps, ARRAY_SIZE(p->adps));
		if (!div) div++;

		div = avr->frequency >> div;
		if (p->first)
			AVR_LOG(avr, LOG_TRACE, "ADC: starting at %uKHz\n", div / 13 / 100);
		div /= p->first ? 25 : 13;	// first cycle is longer

		avr_cycle_timer_register(avr,
				avr_hz_to_cycles(avr, div),
				avr_adc_int_raise, p);
	}
	avr_core_watch_write(avr, addr, v);
}
Exemplo n.º 12
0
/*
 * Write data to the latch, tell the system we have something
 * to send next
 */
static void
avr_twi_write_data(
		struct avr_t * avr,
		avr_io_addr_t addr,
		uint8_t v,
		void * param)
{
	avr_twi_t * p = (avr_twi_t *)param;

	avr_core_watch_write(avr, addr, v);
	// tell system we have something in the write latch
	p->state |= TWI_COND_WRITE;
}
Exemplo n.º 13
0
static void
avr_watchdog_write (avr_t * avr, avr_io_addr_t addr, uint8_t v, void *param)
{
  avr_watchdog_t *p = (avr_watchdog_t *) param;

  uint8_t old_wde = avr_regbit_get (avr, p->wde);
  uint8_t old_wdie = avr_regbit_get (avr, p->watchdog.enable);
  uint8_t old_wdce = avr_regbit_get (avr, p->wdce);

  uint8_t was_enabled = (old_wde || old_wdie);

  uint8_t old_v = avr->data[addr];   // allow gdb to see write...
  avr_core_watch_write (avr, addr, v);

  if (old_wdce)
    {
      uint8_t old_wdp = avr_regbit_get_array (avr, p->wdp, 4);

      // wdrf (watchdog reset flag) must be cleared before wde can be cleared.
      if (avr_regbit_get (avr, p->wdrf))
        avr_regbit_set (avr, p->wde);

      avr_watchdog_set_cycle_count_and_timer (avr, p, was_enabled, old_wdp);
    }
  else
    {
      /* easier to change only what we need rather than check and reset 
       * locked/read-only bits.
       */
      avr->data[addr] = old_v;

      uint8_t wdce_v = avr_regbit_from_value (avr, p->wdce, v);
      uint8_t wde_v = avr_regbit_from_value (avr, p->wde, v);

      if (wdce_v && wde_v)
        {
          avr_regbit_set (avr, p->wdce);

          avr_cycle_timer_register (avr, 4, avr_wdce_clear, p);
        }
      else
        {
          if (wde_v)   // wde can be set but not cleared
            avr_regbit_set (avr, p->wde);

          avr_regbit_setto_raw (avr, p->watchdog.enable, v);

          avr_watchdog_set_cycle_count_and_timer (avr, p, was_enabled, -1);
        }
    }
}
Exemplo n.º 14
0
static void
avr_timer_write(
		struct avr_t * avr,
		avr_io_addr_t addr,
		uint8_t v,
		void * param)
{
	avr_timer_t * p = (avr_timer_t *)param;

	uint8_t as2 = avr_regbit_get(avr, p->as2);
	uint8_t cs = avr_regbit_get_array(avr, p->cs, ARRAY_SIZE(p->cs));
	uint8_t mode = avr_regbit_get_array(avr, p->wgm, ARRAY_SIZE(p->wgm));

	avr_core_watch_write(avr, addr, v);

	uint8_t new_as2 = avr_regbit_get(avr, p->as2);
	uint8_t new_cs = avr_regbit_get_array(avr, p->cs, ARRAY_SIZE(p->cs));
	uint8_t new_mode = avr_regbit_get_array(avr, p->wgm, ARRAY_SIZE(p->wgm));

	// only reconfigure the timer if "relevant" bits have changed
	// this prevent the timer reset when changing the edge detector
	// or other minor bits
	if (new_cs != cs || new_mode != mode || new_as2 != as2) {
	/* cs */
		if (new_cs == 0) {
			// cancel everything
			avr_timer_cancel_all_cycle_timers(avr, p, 1);

			AVR_LOG(avr, LOG_TRACE, "TIMER: %s-%c clock turned off\n",
					__func__, p->name);
			return;
		}

		if (new_as2) {
			// AVR clock and external 32KHz source does not have
			// to be synced. To obtain better simulation results
			// p->tov_base type must be float or avr->frequency
			// must be multiple of 32768.
			p->cs_div_value = (uint32_t)((uint64_t)avr->frequency * (1 << p->cs_div[new_cs]) / 32768);
		} else {
			p->cs_div_value = 1 << p->cs_div[new_cs];
		}

	/* mode */
		p->mode = p->wgm_op[new_mode];
		p->wgm_op_mode_kind = p->mode.kind;
		p->wgm_op_mode_size = (1 << p->mode.size) - 1;

		avr_timer_reconfigure(p, 1);
	}
}
Exemplo n.º 15
0
static void
avr_timer_write_ocr(
		struct avr_t * avr,
		avr_io_addr_t addr,
		uint8_t v,
		void * param)
{
	avr_timer_comp_p comp = (avr_timer_comp_p)param;
	avr_timer_t *timer = comp->timer;
	uint16_t oldv;

	/* check to see if the OCR values actually changed */
	oldv = _timer_get_comp_ocr(avr, comp);
	avr_core_watch_write(avr, addr, v);

	switch (timer->wgm_op_mode_kind) {
		case avr_timer_wgm_normal:
			avr_timer_reconfigure(timer, 0);
			break;
		case avr_timer_wgm_fc_pwm:	// OCR is not used here
			avr_timer_reconfigure(timer, 0);
			break;
		case avr_timer_wgm_ctc:
			avr_timer_reconfigure(timer, 0);
			break;
		case avr_timer_wgm_pwm:
			if (timer->mode.top != avr_timer_wgm_reg_ocra) {
				avr_raise_irq(timer->io.irq + TIMER_IRQ_OUT_PWM0, _timer_get_ocr(timer, AVR_TIMER_COMPA));
			} else {
				avr_timer_reconfigure(timer, 0); // if OCRA is the top, reconfigure needed
			}
			avr_raise_irq(timer->io.irq + TIMER_IRQ_OUT_PWM1, _timer_get_ocr(timer, AVR_TIMER_COMPB));
			break;
		case avr_timer_wgm_fast_pwm:
			if (oldv != _timer_get_comp_ocr(avr, comp))
				avr_timer_reconfigure(timer, 0);
			avr_raise_irq(timer->io.irq + TIMER_IRQ_OUT_PWM0,
					_timer_get_ocr(timer, AVR_TIMER_COMPA));
			avr_raise_irq(timer->io.irq + TIMER_IRQ_OUT_PWM1,
					_timer_get_ocr(timer, AVR_TIMER_COMPB));
			break;
		default:
			AVR_LOG(avr, LOG_WARNING, "TIMER: %s-%c mode %d UNSUPPORTED\n",
					__FUNCTION__, timer->name, timer->mode.kind);
			avr_timer_reconfigure(timer, 0);
			break;
	}
}
Exemplo n.º 16
0
static void
avr_usb_ep_write(
    struct avr_t * avr,
    avr_io_addr_t addr,
    uint8_t v,
    void * param)
{
    avr_usb_t * p = (avr_usb_t *) param;
    struct _epstate * epstate = get_epstate(p, current_ep_to_cpu(p));
    uint8_t laddr = addr - p->r_usbcon;

    switch (laddr) {
    case ueconx:
        if (v & 1 << 4)
            epstate->ueconx.stallrq = 0;
        if (v & 1 << 5)
            epstate->ueconx.stallrq = 1;
        epstate->ueconx.epen = (v & 1) != 0;
        break;
    case uecfg0x:
        epstate->uecfg0x.v = v;
        epstate->uesta0x.cfgok = 0;
        break;
    case uecfg1x:
        epstate->uecfg1x.v = v;
        epstate->uesta0x.cfgok = epstate->uecfg1x.alloc;
        if (epstate->uecfg0x.eptype == 0)
            epstate->ueintx.txini = 1;
        else if (epstate->uecfg0x.epdir) {
            epstate->ueintx.txini = 1;
            epstate->ueintx.rwal = 1;
            epstate->ueintx.fifocon = 1;
        } else
            epstate->ueintx.rxouti = 0;
        avr_core_watch_write(avr, p->r_usbcon + uesta0x,
                             epstate->uesta0x.v);
        break;
    case uesta0x:
        v = (epstate->uesta0x.v & 0x9f) + (v & (0x60 & epstate->uesta0x.v));
        epstate->uesta0x.v = v;
        break;
    case ueienx:
        epstate->ueienx.v = v;
        break;
    default:
        assert(0);
    }
}
Exemplo n.º 17
0
/*
 * prevent code from rewriting out status bits, since we actualy use them!
 */
static void
avr_twi_write_status(
		struct avr_t * avr,
		avr_io_addr_t addr,
		uint8_t v,
		void * param)
{
	avr_twi_t * p = (avr_twi_t *)param;
	uint8_t sr = avr_regbit_get(avr, p->twsr);
	uint8_t c = avr_regbit_get(avr, p->twps);

	avr_core_watch_write(avr, addr, v);
	avr_regbit_setto(avr, p->twsr, sr);	// force restore

	if (c != avr_regbit_get(avr, p->twps)) {
		// prescaler bits changed...
	}
}
Exemplo n.º 18
0
static void avr_timer_write_ocr(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
{
	avr_timer_t * p = (avr_timer_t *)param;
	uint16_t oldv[AVR_TIMER_COMP_COUNT];
	int target = -1;

	/* check to see if the OCR values actually changed */
	for (int oi = 0; oi < AVR_TIMER_COMP_COUNT; oi++)
		oldv[oi] = _timer_get_ocr(p, oi);
	avr_core_watch_write(avr, addr, v);
	for (int oi = 0; oi < AVR_TIMER_COMP_COUNT; oi++)
		if (oldv[oi] != _timer_get_ocr(p, oi)) {
			target = oi;
			break;
		}

	switch (p->mode.kind) {
		case avr_timer_wgm_normal:
			avr_timer_reconfigure(p);
			break;
		case avr_timer_wgm_fc_pwm:	// OCR is not used here
			avr_timer_reconfigure(p);
			break;
		case avr_timer_wgm_ctc:
			avr_timer_reconfigure(p);
			break;
		case avr_timer_wgm_pwm:
			if (p->mode.top != avr_timer_wgm_reg_ocra) {
				avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM0, _timer_get_ocr(p, AVR_TIMER_COMPA));
				avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM1, _timer_get_ocr(p, AVR_TIMER_COMPB));
			}
			break;
		case avr_timer_wgm_fast_pwm:
			if (target != -1)
				avr_timer_reconfigure(p);
			avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM0, _timer_get_ocr(p, AVR_TIMER_COMPA));
			avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM1, _timer_get_ocr(p, AVR_TIMER_COMPB));
			break;
		default:
			AVR_LOG(avr, LOG_WARNING, "TIMER: %s-%c mode %d UNSUPPORTED\n", __FUNCTION__, p->name, p->mode.kind);
			avr_timer_reconfigure(p);
			break;
	}
}
Exemplo n.º 19
0
static void avr_timer_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
{
	avr_timer_t * p = (avr_timer_t *)param;

	uint8_t as2 = avr_regbit_get(avr, p->as2);
	uint8_t cs = avr_regbit_get_array(avr, p->cs, ARRAY_SIZE(p->cs));
	uint8_t mode = avr_regbit_get_array(avr, p->wgm, ARRAY_SIZE(p->wgm));

	avr_core_watch_write(avr, addr, v);

	// only reconfigure the timer if "relevant" bits have changed
	// this prevent the timer reset when changing the edge detector
	// or other minor bits
	if (avr_regbit_get_array(avr, p->cs, ARRAY_SIZE(p->cs)) != cs ||
			avr_regbit_get_array(avr, p->wgm, ARRAY_SIZE(p->wgm)) != mode ||
					avr_regbit_get(avr, p->as2) != as2) {
		avr_timer_reconfigure(p);
	}
}
Exemplo n.º 20
0
static void avr_watchdog_write(avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
{
	avr_watchdog_t * p = (avr_watchdog_t *)param;
	// backup the registers
	// uint8_t wd = avr->data[p->wdce.reg];
	uint8_t wdce_o = avr_regbit_get(avr, p->wdce);	// old
	uint8_t wde_o = avr_regbit_get(avr, p->wde);
	uint8_t wdp_o[4];

//	printf("avr_watchdog_write %02x\n", v);
	for (int i = 0; i < 4; i++)
		wdp_o[i] = avr_regbit_get(avr, p->wdp[i]);

	avr->data[p->wdce.reg] = v;
	uint8_t wdce_n = avr_regbit_get(avr, p->wdce);	// new

	if (wdce_o /* || wdce_n */) {
		// make sure bit gets reset eventually
		if (wdce_n)
			avr_cycle_timer_register(avr, 4, avr_wdce_clear, p);

		uint8_t wdp = avr_regbit_get_array(avr, p->wdp, 4);
		p->cycle_count = 2048 << wdp;
		p->cycle_count = (p->cycle_count * avr->frequency) / 128000;
		if (avr_regbit_get(avr, p->wde)) {
			printf("Watchdog reset to %d cycles @ 128kz (* %d) = %d CPU cycles)\n", 2048 << wdp, 1 << wdp, (int)p->cycle_count);
			avr_cycle_timer_register(avr, p->cycle_count, avr_watchdog_timer, p);
		} else {
			printf("Watchdog disabled\n");
			avr_cycle_timer_cancel(avr, avr_watchdog_timer, p);
		}
	} else {
		// reset old values
		avr_regbit_setto(avr, p->wde, wde_o);
		for (int i = 0; i < 4; i++)
			avr_regbit_setto(avr, p->wdp[i], wdp_o[i]);
		v = avr->data[p->wdce.reg];
	}
	avr_core_watch_write(avr, addr, v);
}
Exemplo n.º 21
0
static void avr_uart_baud_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
{
	avr_uart_t * p = (avr_uart_t *)param;
	avr_core_watch_write(avr, addr, v);
	uint32_t val = avr->data[p->r_ubrrl] | (avr->data[p->r_ubrrh] << 8);
	uint32_t baud = avr->frequency / (val+1);
	if (avr_regbit_get(avr, p->u2x))
		baud /= 8;
	else
		baud /= 16;

	const int databits[] = { 5,6,7,8,  /* 'reserved', assume 8 */8,8,8, 9 };
	int db = databits[avr_regbit_get(avr, p->ucsz) | (avr_regbit_get(avr, p->ucsz2) << 2)];
	int sb = 1 + avr_regbit_get(avr, p->usbs);
	int word_size = 1 /* start */ + db /* data bits */ + 1 /* parity */ + sb /* stops */;

	AVR_LOG(avr, LOG_TRACE, "UART: %c configured to %04x = %d bps (x%d), %d data %d stop\n",
			p->name, val, baud, avr_regbit_get(avr, p->u2x)?2:1, db, sb);
	// TODO: Use the divider value and calculate the straight number of cycles
	p->usec_per_byte = 1000000 / (baud / word_size);
	AVR_LOG(avr, LOG_TRACE, "UART: Roughly %d usec per bytes\n", (int)p->usec_per_byte);
}
Exemplo n.º 22
0
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;
	}
}