示例#1
0
static avr_cycle_count_t avr_timer_comp(avr_timer_t *p, avr_cycle_count_t when, uint8_t comp)
{
	avr_t * avr = p->io.avr;
	avr_raise_interrupt(avr, &p->comp[comp].interrupt);

	// check output compare mode and set/clear pins
	uint8_t mode = avr_regbit_get(avr, p->comp[comp].com);
	avr_irq_t * irq = &p->io.irq[TIMER_IRQ_OUT_COMP + comp];

	switch (mode) {
		case avr_timer_com_normal: // Normal mode OCnA disconnected
			break;
		case avr_timer_com_toggle: // Toggle OCnA on compare match
			if (p->comp[comp].com_pin.reg)	// we got a physical pin
				avr_raise_irq(irq,
						AVR_IOPORT_OUTPUT | (avr_regbit_get(avr, p->comp[comp].com_pin) ? 0 : 1));
			else // no pin, toggle the IRQ anyway
				avr_raise_irq(irq,
						p->io.irq[TIMER_IRQ_OUT_COMP + comp].value ? 0 : 1);
			break;
		case avr_timer_com_clear:
			avr_raise_irq(irq, 0);
			break;
		case avr_timer_com_set:
			avr_raise_irq(irq, 1);
			break;
	}

	return p->tov_cycles ? 0 :
				p->comp[comp].comp_cycles ?
						when + p->comp[comp].comp_cycles : 0;
}
示例#2
0
static uint8_t avr_uart_rxc_read(struct avr_t * avr, avr_io_addr_t addr, void * param)
{
	avr_uart_t * p = (avr_uart_t *)param;
	uint8_t v = avr_core_watch_read(avr, addr);

	//static uint8_t old = 0xff; if (v != old) printf("UCSRA read %02x\n", v); old = v;
	//
	// if RX is enabled, and there is nothing to read, and
	// the AVR core is reading this register, it's probably
	// to poll the RXC TXC flag and spinloop
	// so here we introduce a usleep to make it a bit lighter
	// on CPU and let data arrive
	//
	uint8_t ri = !avr_regbit_get(avr, p->rxen) || !avr_regbit_get(avr, p->rxc.raised);
	uint8_t ti = !avr_regbit_get(avr, p->txen) || !avr_regbit_get(avr, p->txc.raised);

	if (p->flags & AVR_UART_FLAG_POOL_SLEEP) {

		if (ri && ti)
			usleep(1);
	}
	// if reception is idle and the fifo is empty, tell whomever there is room
	if (avr_regbit_get(avr, p->rxen) && uart_fifo_isempty(&p->input)) {
		avr_raise_irq(p->io.irq + UART_IRQ_OUT_XOFF, 0);
		avr_raise_irq(p->io.irq + UART_IRQ_OUT_XON, 1);
	}

	return v;
}
示例#3
0
static void
avr_timer_comp_on_tov(
		avr_timer_t *p,
		avr_cycle_count_t when,
		uint8_t comp)
{
	avr_t * avr = p->io.avr;

	// check output compare mode and set/clear pins
	uint8_t mode = avr_regbit_get(avr, p->comp[comp].com);
	avr_irq_t * irq = &p->io.irq[TIMER_IRQ_OUT_COMP + comp];

	switch (mode) {
		case avr_timer_com_normal: // Normal mode
			break;
		case avr_timer_com_toggle: // toggle on compare match => on tov do nothing
			break;
		case avr_timer_com_clear: // clear on compare match => set on tov
			avr_raise_irq(irq, 1);
			break;
		case avr_timer_com_set: // set on compare match => clear on tov
			avr_raise_irq(irq, 0);
			break;
	}
}
示例#4
0
/*
 * check whether interrupts are pending. If so, check if the interrupt "latency" is reached,
 * and if so triggers the handlers and jump to the vector.
 */
void
avr_service_interrupts(
		avr_t * avr)
{
	if (!avr->sreg[S_I] || !avr->interrupt_state)
		return;

	if (avr->interrupt_state < 0) {
		avr->interrupt_state++;
		if (avr->interrupt_state == 0)
			avr->interrupt_state = avr_has_pending_interrupts(avr);
		return;
	}

	avr_int_table_p table = &avr->interrupts;

	// how many are pending...
	int cnt = avr_int_pending_get_read_size(&table->pending);
	// locate the highest priority one
	int min = 0xff;
	int mini = 0;
	for (int ii = 0; ii < cnt; ii++) {
		avr_int_vector_t * v = avr_int_pending_read_at(&table->pending, ii);
		if (v->vector < min) {
			min = v->vector;
			mini = ii;
		}
	}
	avr_int_vector_t * vector = avr_int_pending_read_at(&table->pending, mini);

	// now move the one at the front of the fifo in the slot of
	// the one we service
	table->pending.buffer[(table->pending.read + mini) % avr_int_pending_fifo_size] =
			avr_int_pending_read(&table->pending);
	avr_raise_irq(avr->interrupts.irq + AVR_INT_IRQ_PENDING,
			avr_has_pending_interrupts(avr));

	// if that single interrupt is masked, ignore it and continue
	// could also have been disabled, or cleared
	if (!avr_regbit_get(avr, vector->enable) || !vector->pending) {
		vector->pending = 0;
		avr->interrupt_state = avr_has_pending_interrupts(avr);
	} else {
		if (vector && vector->trace)
			printf("%s calling %d\n", __FUNCTION__, (int)vector->vector);
		_avr_push_addr(avr, avr->pc);
		avr_sreg_set(avr, S_I, 0);
		avr->pc = vector->vector * avr->vector_size;

		avr_raise_irq(vector->irq + AVR_INT_IRQ_RUNNING, 1);
		avr_raise_irq(table->irq + AVR_INT_IRQ_RUNNING, vector->vector);
		if (table->running_ptr == ARRAY_SIZE(table->running)) {
			AVR_LOG(avr, LOG_ERROR, "%s run out of nested stack!", __func__);
		} else {
			table->running[table->running_ptr++] = vector;
		}
		avr_clear_interrupt(avr, vector);
	}
}
/**
 * Lowers the card presence signal.
 * This causes the clock to start, which initiates
 * the clock-and-data transfer.
 *
 * @param struct avr_t *avr The AVR this card reader is interfacing with.
 * @param avr_cycle_count_t when The number of cycles since this function call was registered.
 * @param void *param The card_reader struct to raise the card presence signal on.
 * @return avr_cycle_count_t The value of the card presence pin.
 */
avr_cycle_count_t card_reader_lower_presence_signal(struct avr_t *avr, avr_cycle_count_t when, void *param) {
	card_reader_t *self = (card_reader_t *) param;

	avr_raise_irq(avr_io_getirq(self->avr, AVR_IOCTL_IOPORT_GETIRQ('D'), 2), 0);
	avr_raise_irq(avr_io_getirq(self->avr, AVR_IOCTL_IOPORT_GETIRQ('D'), 3), 0);
	avr_cycle_timer_register(avr, self->clock->signal_time, card_reader_clock_tick, self->clock);

	return 0;
}
示例#6
0
/* this is called uppon RETI. */
void
avr_interrupt_reti(
		struct avr_t * avr)
{
	avr_int_table_p table = &avr->interrupts;
	if (table->running_ptr) {
		avr_int_vector_t * vector = table->running[--table->running_ptr];
		avr_raise_irq(vector->irq + AVR_INT_IRQ_RUNNING, 0);
	}
	avr_raise_irq(table->irq + AVR_INT_IRQ_RUNNING,
			table->running_ptr > 0 ?
					table->running[table->running_ptr-1]->vector : 0);
	avr_raise_irq(avr->interrupts.irq + AVR_INT_IRQ_PENDING,
			avr_has_pending_interrupts(avr));
}
示例#7
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;
	}
}
示例#8
0
/*
 * called when the ADC could use a new value
 * The value returned is NOT in "ADC" mode, it's in millivolts
 */
static void
thermistor_in_hook (struct avr_irq_t *irq, uint32_t value, void *param)
{
  thermistor_p p = (thermistor_p) param;
  avr_adc_mux_t v = *((avr_adc_mux_t *) & value);

  // printf("%s(%2d/%2d)\n", __func__, p->adc_mux_number, v.src);

  if (v.src != p->adc_mux_number)
    return;

  short *t = p->table;
  for (int ei = 0; ei < p->table_entries; ei++, t += 2)
    {
      if (t[1] <= p->current)
        {
	  // printf("%s(%2d) %.2f matches %3dC is %d adc\n", __func__, v.src,
	  //        p->current, t[1], t[0] / p->oversampling);
          avr_raise_irq (p->irq + IRQ_TERM_ADC_VALUE_OUT, ((t[0] / p->oversampling) * 5000) / 0x3ff);
          return;
        }
    }

  printf ("%s(%d) temperature out of range (%.2f), we're screwed\n",
          __func__, p->adc_mux_number, p->current);
}
示例#9
0
文件: hc595.c 项目: jcadel/simavr
/*
 * called when a SPI byte is sent
 */
static void hc595_spi_in_hook(struct avr_irq_t * irq, uint32_t value, void * param)
{
    hc595_t * p = (hc595_t*)param;
    // send "old value" to any chained one..
    avr_raise_irq(p->irq + IRQ_HC595_SPI_BYTE_OUT, p->value);
    p->value = (p->value << 8) | (value & 0xff);
}
示例#10
0
void
thermistor_set_temp (thermistor_p p, float temp)
{
  uint32_t value = temp * 256;
  p->current = temp;
  avr_raise_irq (p->irq + IRQ_TERM_TEMP_VALUE_OUT, value);
}
示例#11
0
文件: hc595.c 项目: jcadel/simavr
/*
 * called when a LATCH signal is sent
 */
static void hc595_latch_hook(struct avr_irq_t * irq, uint32_t value, void * param)
{
    hc595_t * p = (hc595_t*)param;
    if (irq->value && !value) {	// falling edge
        p->latch = p->value;
        avr_raise_irq(p->irq + IRQ_HC595_OUT, p->latch);
    }
}
/**
 * Raises the card presence signal.
 * The clock signal is expected to already have stopped,
 * and the data buffer for the DATA pin will be reset.
 *
 * @param struct avr_t *avr The AVR this card reader is interfacing with.
 * @param avr_cycle_count_t when The number of cycles since this function call was registered.
 * @param void *param The card_reader struct to raise the card presence signal on.
 * @return avr_cycle_count_t The value of the card presence pin.
 */
avr_cycle_count_t card_reader_raise_presence_signal(struct avr_t *avr, avr_cycle_count_t when, void *param) {
	card_reader_t *self = (card_reader_t *) param;

	avr_raise_irq(avr_io_getirq(self->avr, AVR_IOCTL_IOPORT_GETIRQ('D'), 2), 1);
	self->swipe_buffer_pos = 0;

	return 0;
}
示例#13
0
static void
thermistor_value_in_hook (struct avr_irq_t *irq, uint32_t value, void *param)
{
  thermistor_p p = (thermistor_p) param;
  float fv = ((float) value) / 256;
  p->current = fv;
  avr_raise_irq (p->irq + IRQ_TERM_TEMP_VALUE_OUT, value);
}
示例#14
0
void
avr_clear_interrupt(
		avr_t * avr,
		avr_int_vector_t * vector)
{
	if (!vector)
		return;
	if (vector->trace)
		printf("%s cleared %d\n", __FUNCTION__, vector->vector);
	vector->pending = 0;

	avr_raise_irq(vector->irq + AVR_INT_IRQ_PENDING, 0);
	avr_raise_irq(avr->interrupts.irq + AVR_INT_IRQ_PENDING,
			avr_has_pending_interrupts(avr));

	if (vector->raised.reg && !vector->raise_sticky)
		avr_regbit_clear(avr, vector->raised);
}
示例#15
0
文件: avr_usb.c 项目: jcadel/simavr
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);
}
示例#16
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;
	}
}
示例#17
0
static avr_cycle_count_t
switch_auto(struct avr_t * avr,
        avr_cycle_count_t when, void * param)
{
	ac_input_t * b = (ac_input_t *) param;
	b->value = !b->value;
//printf("ac=%d\n", b->value);
	avr_raise_irq(b->irq + IRQ_AC_OUT, b->value);
	return when + avr_usec_to_cycles(avr, 100000 / 50);
}
示例#18
0
int
avr_raise_interrupt(
		avr_t * avr,
		avr_int_vector_t * vector)
{
	if (!vector || !vector->vector)
		return 0;
	if (vector->trace)
		printf("%s raising %d (enabled %d)\n", __FUNCTION__, vector->vector, avr_regbit_get(avr, vector->enable));
	if (vector->pending) {
		if (vector->trace)
			printf("%s trying to double raise %d (enabled %d)\n", __FUNCTION__, vector->vector, avr_regbit_get(avr, vector->enable));
		return 0;
	}
	// always mark the 'raised' flag to one, even if the interrupt is disabled
	// this allow "polling" for the "raised" flag, like for non-interrupt
	// driven UART and so so. These flags are often "write one to clear"
	if (vector->raised.reg)
		avr_regbit_set(avr, vector->raised);

	avr_raise_irq(vector->irq + AVR_INT_IRQ_PENDING, 1);
	avr_raise_irq(avr->interrupts.irq + AVR_INT_IRQ_PENDING, 1);

	// If the interrupt is enabled, attempt to wake the core
	if (avr_regbit_get(avr, vector->enable)) {
		// Mark the interrupt as pending
		vector->pending = 1;

		avr_int_table_p table = &avr->interrupts;

		avr_int_pending_write(&table->pending, vector);

		if (avr->sreg[S_I] && avr->interrupt_state == 0)
			avr->interrupt_state = 1;
		if (avr->state == cpu_Sleeping) {
			if (vector->trace)
				printf("Waking CPU due to interrupt\n");
			avr->state = cpu_Running;	// in case we were sleeping
		}
	}
	// return 'raised' even if it was already pending
	return 1;
}
示例#19
0
文件: avr_adc.c 项目: kevinf28/simavr
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);
}
示例#20
0
static avr_cycle_count_t avr_spi_raise(struct avr_t * avr, avr_cycle_count_t when, void * param)
{
    avr_spi_t * p = (avr_spi_t *)param;

    if (avr_regbit_get(avr, p->spe)) {
        // in master mode, any byte is sent as it comes..
        if (avr_regbit_get(avr, p->mstr)) {
            avr_raise_interrupt(avr, &p->spi);
            avr_raise_irq(p->io.irq + SPI_IRQ_OUTPUT, avr->data[p->r_spdr]);
        }
    }
    return 0;
}
示例#21
0
文件: avr_twi.c 项目: Axbit/simavr
static inline void
_avr_twi_status_set(
		avr_twi_t * p,
		uint8_t v,
		int interrupt)
{
	avr_regbit_setto_raw(p->io.avr, p->twsr, v);
#if AVR_TWI_DEBUG
	AVR_TRACE(p->io.avr, "%s %02x\n", __func__, v);
#endif
	avr_raise_irq(p->io.irq + TWI_IRQ_STATUS, v);
	if (interrupt)
		avr_raise_interrupt(p->io.avr, &p->twi);
}
示例#22
0
/*
 * Called when the uart has room in it's input buffer. This is called repeateadly
 * if necessary, while the xoff is called only when the uart fifo is FULL
 */
static void uart_udp_xon_hook(struct avr_irq_t * irq, uint32_t value, void * param)
{
	uart_udp_t * p = (uart_udp_t*)param;
//	if (!p->xon)
//		printf("uart_udp_xon_hook\n");
	p->xon = 1;
	// try to empty our fifo, the uart_udp_xoff_hook() will be called when
	// other side is full
	while (p->xon && !uart_udp_fifo_isempty(&p->out)) {
		uint8_t byte = uart_udp_fifo_read(&p->out);
	//	printf("uart_udp_xon_hook send %02x\n", byte);
		avr_raise_irq(p->irq + IRQ_UART_UDP_BYTE_OUT, byte);
	}
}
示例#23
0
void
avr_clear_interrupt(
		avr_t * avr,
		avr_int_vector_t * vector)
{
	if (!vector)
		return;
	if (vector->trace)
		printf("%s cleared %d\n", __FUNCTION__, vector->vector);
	vector->pending = 0;
	avr_raise_irq(&vector->irq, 0);
	if (vector->raised.reg && !vector->raise_sticky)
		avr_regbit_clear(avr, vector->raised);
}
示例#24
0
static avr_cycle_count_t avr_adc_int_raise(struct avr_t * avr, avr_cycle_count_t when, void * param)
{
	avr_adc_t * p = (avr_adc_t *)param;
	if (avr_regbit_get(avr, p->aden)) {
		// if the interrupts are not used, still raised the UDRE and TXC flag
		avr_raise_interrupt(avr, &p->adc);
		avr_regbit_clear(avr, p->adsc);
		p->first = 0;
		p->read_status = 0;
		if( p->adts_mode == avr_adts_free_running )
			avr_raise_irq(p->io.irq + ADC_IRQ_IN_TRIGGER, 1);
	}
	return 0;
}
示例#25
0
int
avr_clear_interrupt_if(
		avr_t * avr,
		avr_int_vector_t * vector,
		uint8_t old)
{
	avr_raise_irq(avr->interrupts.irq + AVR_INT_IRQ_PENDING,
			avr_has_pending_interrupts(avr));
	if (avr_regbit_get(avr, vector->raised)) {
		avr_clear_interrupt(avr, vector);
		return 1;
	}
	avr_regbit_setto(avr, vector->raised, old);
	return 0;
}
示例#26
0
static uint8_t
avr_ioport_read(
		struct avr_t * avr,
		avr_io_addr_t addr,
		void * param)
{
	avr_ioport_t * p = (avr_ioport_t *)param;
	uint8_t ddr = avr->data[p->r_ddr];
	uint8_t v = (avr->data[p->r_pin] & ~ddr) | (avr->data[p->r_port] & ddr);
	avr->data[addr] = v;
	// made to trigger potential watchpoints
	v = avr_core_watch_read(avr, addr);
	avr_raise_irq(p->io.irq + IOPORT_IRQ_REG_PIN, v);
	D(if (avr->data[addr] != v) printf("** PIN%c(%02x) = %02x\r\n", p->name, addr, v);)

	return v;
示例#27
0
static void avr_spi_irq_input(struct avr_irq_t * irq, uint32_t value, void * param)
{
    avr_spi_t * p = (avr_spi_t *)param;
    avr_t * avr = p->io.avr;

    // check to see if receiver is enabled
    if (!avr_regbit_get(avr, p->spe))
        return;

    // double buffer the input.. ?
    p->input_data_register = value;
    avr_raise_interrupt(avr, &p->spi);

    // if in slave mode,
    // 'output' the byte only when we received one...
    if (!avr_regbit_get(avr, p->mstr)) {
        avr_raise_irq(p->io.irq + SPI_IRQ_OUTPUT, avr->data[p->r_spdr]);
    }
}
示例#28
0
/*
 * Set a register (r < 256)
 * if it's an IO register (> 31) also (try to) call any callback that was
 * registered to track changes to that register.
 */
static inline void _avr_set_r(avr_t * avr, uint8_t r, uint8_t v)
{
	REG_TOUCH(avr, r);

	if (r == R_SREG) {
		avr->data[R_SREG] = v;
		// unsplit the SREG
		SET_SREG_FROM(avr, v);
		SREG();
	}
	if (r > 31) {
		uint8_t io = AVR_DATA_TO_IO(r);
		if (avr->io[io].w.c)
			avr->io[io].w.c(avr, r, v, avr->io[io].w.param);
		else
			avr->data[r] = v;
		if (avr->io[io].irq) {
			avr_raise_irq(avr->io[io].irq + AVR_IOMEM_IRQ_ALL, v);
			for (int i = 0; i < 8; i++)
				avr_raise_irq(avr->io[io].irq + i, (v >> i) & 1);				
		}
示例#29
0
文件: simul.c 项目: fvicente/binw2
int main(int argc, char *argv[])
{
	elf_firmware_t		f;
	const char			*fname="../src/binw2.elf";
	const char			*mmcu="attiny13";

	elf_read_firmware(fname, &f);

	snprintf(f.mmcu, sizeof(f.mmcu) - 1, "%s", mmcu);
	f.frequency = 4800000;
	printf("firmware %s f=%d mmcu=%s\n", fname, (int)f.frequency, f.mmcu);

	avr = avr_make_mcu_by_name(f.mmcu);
	if (!avr) {
		fprintf(stderr, "%s: AVR '%s' not known\n", argv[0], f.mmcu);
		exit(1);
	}
	avr_init(avr);
	avr_load_firmware(avr, &f);

	// initialize our 'peripheral'
	button_init(avr, &button, "button");

	// "connect" the output irq of the button to the port pin of the AVR
	avr_connect_irq(
		button.irq + IRQ_BUTTON_OUT,
		avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), IOPORT_IRQ_PIN4));

	avr_irq_register_notify(
		avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), IOPORT_IRQ_DIRECTION_ALL),
		ddr_hook,
		NULL);

	avr_irq_register_notify(
		avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), IOPORT_IRQ_PIN_ALL),
		pin_changed_hook, 
		"portb");

	// even if not setup at startup, activate gdb if crashing
	avr->gdb_port = 1234;
	//if (0) {
	//	//avr->state = cpu_Stopped;
	//	avr_gdb_init(avr);
	//}

	/*
	 *	VCD file initialization
	 *	
	 *	This will allow you to create a "wave" file and display it in gtkwave
	 *	Pressing "r" and "s" during the demo will start and stop recording
	 *	the pin changes
	 */
	avr_vcd_init(avr, "gtkwave_output.vcd", &vcd_file, 100000 /* usec */);
	avr_vcd_add_signal(&vcd_file, 
		avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), IOPORT_IRQ_PIN_ALL), 8 /* bits */ ,
		"portb" );
	avr_vcd_add_signal(&vcd_file, 
		button.irq + IRQ_BUTTON_OUT, 1 /* bits */ ,
		"button" );

	// 'raise' it, it's a "pullup"
	avr_raise_irq(button.irq + IRQ_BUTTON_OUT, 0);

	printf( "Launching binw2 simulation\n"
			"   Press 'space' to press virtual button attached to pin %d\n"
			"   Press 'q' to quit\n"
			"   Press 'r' to start recording a 'wave' file\n"
			"   Press 's' to stop recording\n",
			IOPORT_IRQ_PIN4);

	/*
	 * OpenGL init, can be ignored
	 */
	glutInit(&argc, argv);		/* initialize GLUT system */

	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
	glutInitWindowSize(5 * SZ_PIXSIZE, 7 * SZ_PIXSIZE);
	window = glutCreateWindow("Glut");	/* create window */

	// Set up projection matrix
	glMatrixMode(GL_PROJECTION); // Select projection matrix
	glLoadIdentity(); // Start with an identity matrix
	glOrtho(0, 5 * SZ_PIXSIZE, 0, 7 * SZ_PIXSIZE, 0, 10);
	//glScalef(1, -1, 1);
	//glTranslatef(0, -7 * SZ_PIXSIZE, 0);

	glutDisplayFunc(displayCB);		/* set window's display callback */
	glutKeyboardFunc(keyCB);		/* set window's key callback */
	glutTimerFunc(1000 / 24, timerCB, 0);

	// the AVR run on it's own thread. it even allows for debugging!
	pthread_t run;
	pthread_create(&run, NULL, avr_run_thread, NULL);

	glutMainLoop();
}
示例#30
0
int main(int argc, char *argv[])
{
	elf_firmware_t f;
	//const char * fname =  "atmega48_ledramp.axf";
	const char * fname =  argv[1];
	char path[256];

//	sprintf(path, "%s/%s", dirname(argv[0]), fname);
//	printf("Firmware pathname is %s\n", path);
	elf_read_firmware(fname, &f);

	printf("firmware %s f=%d mmcu=%s\n", fname, (int)f.frequency, f.mmcu);

	avr = avr_make_mcu_by_name(f.mmcu);
	if (!avr) {
		fprintf(stderr, "%s: AVR '%s' now known\n", argv[0], f.mmcu);
		exit(1);
	}
	avr_init(avr);
	avr_load_firmware(avr, &f);

	// initialize our 'peripheral'
	button_init(avr, &button, "button");
	// "connect" the output irw of the button to the port pin of the AVR
	avr_connect_irq(
		button.irq + IRQ_BUTTON_OUT,
		avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('C'), 0));

	// connect all the pins on port B to our callback
	for (int i = 0; i < 8; i++)
		avr_irq_register_notify(
			avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), i),
			pin_changed_hook, 
			NULL);

	// even if not setup at startup, activate gdb if crashing
	avr->gdb_port = 1234;
	if (0) {
		//avr->state = cpu_Stopped;
		avr_gdb_init(avr);
	}

	/*
	 *	VCD file initialization
	 *	
	 *	This will allow you to create a "wave" file and display it in gtkwave
	 *	Pressing "r" and "s" during the demo will start and stop recording
	 *	the pin changes
	 */
	avr_vcd_init(avr, "gtkwave_output.vcd", &vcd_file, 100000 /* usec */);
	avr_vcd_add_signal(&vcd_file, 
		avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), IOPORT_IRQ_PIN_ALL), 8 /* bits */ ,
		"portb" );
	avr_vcd_add_signal(&vcd_file, avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('C'), IOPORT_IRQ_PIN0), 1, "portc");
	avr_vcd_add_signal(&vcd_file, 
		button.irq + IRQ_BUTTON_OUT, 1 /* bits */ ,
		"button" );

	// 'raise' it, it's a "pullup"
	avr_raise_irq(button.irq + IRQ_BUTTON_OUT, 1);

	printf( "Demo launching: 'LED' bar is PORTB, updated every 1/64s by the AVR\n"
			"   firmware using a timer. If you press 'space' this presses a virtual\n"
			"   'button' that is hooked to the virtual PORTC pin 0 and will\n"
			"   trigger a 'pin change interrupt' in the AVR core, and will 'invert'\n"
			"   the display.\n"
			"   Press 'q' to quit\n\n"
			"   Press 'r' to start recording a 'wave' file\n"
			"   Press 's' to stop recording\n"
			);

	/*
	 * OpenGL init, can be ignored
	 */
	glutInit(&argc, argv);		/* initialize GLUT system */

	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
	glutInitWindowSize(8 * pixsize, 1 * pixsize);		/* width=400pixels height=500pixels */
	window = glutCreateWindow("Glut");	/* create window */

	// Set up projection matrix
	glMatrixMode(GL_PROJECTION); // Select projection matrix
	glLoadIdentity(); // Start with an identity matrix
	glOrtho(0, 8 * pixsize, 0, 1 * pixsize, 0, 10);
	glScalef(1,-1,1);
	glTranslatef(0, -1 * pixsize, 0);

	glutDisplayFunc(displayCB);		/* set window's display callback */
	glutKeyboardFunc(keyCB);		/* set window's key callback */
	glutTimerFunc(1000 / 24, timerCB, 0);

	// the AVR run on it's own thread. it even allows for debugging!
	pthread_t run;
	pthread_create(&run, NULL, avr_run_thread, NULL);

	glutMainLoop();
}