Пример #1
0
static uint8_t avr_uart_read(struct avr_t * avr, avr_io_addr_t addr, void * param)
{
	avr_uart_t * p = (avr_uart_t *)param;

	// clear the rxc bit in case the code is using polling
	avr_regbit_clear(avr, p->rxc.raised);

	if (!avr_regbit_get(avr, p->rxen)) {
		avr->data[addr] = 0;
		// made to trigger potential watchpoints
		avr_core_watch_read(avr, addr);
		return 0;
	}
	uint8_t v = uart_fifo_read(&p->input);

//	TRACE(printf("UART read %02x %s\n", v, uart_fifo_isempty(&p->input) ? "EMPTY!" : "");)
	avr->data[addr] = v;
	// made to trigger potential watchpoints
	v = avr_core_watch_read(avr, addr);

	// trigger timer if more characters are pending
	if (!uart_fifo_isempty(&p->input))
		avr_cycle_timer_register_usec(avr, p->usec_per_byte, avr_uart_rxc_raise, p);

	return v;
}
Пример #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 uint8_t avr_timer_tcnt_read(struct avr_t * avr, avr_io_addr_t addr, void * param)
{
	avr_timer_t * p = (avr_timer_t *)param;
	// made to trigger potential watchpoints

	uint16_t tcnt = _avr_timer_get_current_tcnt(p);

	avr->data[p->r_tcnt] = tcnt;
	if (p->r_tcnth)
		avr->data[p->r_tcnth] = tcnt >> 8;
	
	return avr_core_watch_read(avr, addr);
}
Пример #4
0
/*
 * From Datasheet:
 * "When ADCL is read, the ADC Data Register is not updated until ADCH is read.
 * Consequently, if the result is left adjusted and no more than 8-bit
 * precision is required, it is sufficient to read ADCH.
 * Otherwise, ADCL must be read first, then ADCH."
 * So here if the H is read before the L, we still call the L to update the
 * register value.
 */
static uint8_t avr_adc_read_h(struct avr_t * avr, avr_io_addr_t addr, void * param)
{
	avr_adc_t * p = (avr_adc_t *)param;
	// no "break" here on purpose
	switch (p->read_status) {
		case 0:
			avr_adc_read_l(avr, p->r_adcl, param);
		case 1:
			p->read_status = 2;
		default:
			return avr_core_watch_read(avr, addr);
	}
}
Пример #5
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;
Пример #6
0
static uint8_t
avr_adc_read_l(
		struct avr_t * avr, avr_io_addr_t addr, void * param)
{
	avr_adc_t * p = (avr_adc_t *)param;

	if (p->read_status)	// conversion already done
		return avr_core_watch_read(avr, addr);

	uint8_t refi = avr_regbit_get_array(avr, p->ref, ARRAY_SIZE(p->ref));
	uint16_t ref = p->ref_values[refi];
	uint8_t muxi = avr_regbit_get_array(avr, p->mux, ARRAY_SIZE(p->mux));
	avr_adc_mux_t mux = p->muxmode[muxi];
	// optional shift left/right
	uint8_t shift = avr_regbit_get(avr, p->adlar) ? 6 : 0; // shift LEFT

	uint32_t reg = 0;
	switch (mux.kind) {
		case ADC_MUX_SINGLE:
			reg = p->adc_values[mux.src];
			break;
		case ADC_MUX_DIFF:
			if (mux.gain == 0)
				mux.gain = 1;
			reg = ((uint32_t)p->adc_values[mux.src] * mux.gain) -
					((uint32_t)p->adc_values[mux.diff] * mux.gain);
			break;
		case ADC_MUX_TEMP:
			reg = p->temp; // assumed to be already calibrated somehow
			break;
		case ADC_MUX_REF:
			reg = mux.src; // reference voltage
			break;
		case ADC_MUX_VCC4:
			if ( !avr->vcc) {
				AVR_LOG(avr, LOG_WARNING, "ADC: missing VCC analog voltage\n");
			} else
				reg = avr->vcc / 4;
			break;
	}
	uint32_t vref = 3300;
	switch (ref) {
		case ADC_VREF_VCC:
			if (!avr->vcc)
				AVR_LOG(avr, LOG_WARNING, "ADC: missing VCC analog voltage\n");
			else
				vref = avr->vcc;
			break;
		case ADC_VREF_AREF:
			if (!avr->aref)
				AVR_LOG(avr, LOG_WARNING, "ADC: missing AREF analog voltage\n");
			else
				vref = avr->aref;
			break;
		case ADC_VREF_AVCC:
			if (!avr->avcc)
				AVR_LOG(avr, LOG_WARNING, "ADC: missing AVCC analog voltage\n");
			else
				vref = avr->avcc;
			break;
		default:
			vref = ref;
	}
//	printf("ADCL %d:%3d:%3d read %4d vref %d:%d=%d\n",
//			mux.kind, mux.diff, mux.src,
//			reg, refi, ref, vref);
	reg = (reg * 0x3ff) / vref;	// scale to 10 bits ADC
//	printf("ADC to 10 bits 0x%x %d\n", reg, reg);
	if (reg > 0x3ff) {
		AVR_LOG(avr, LOG_WARNING, "ADC: channel %d clipped %u/%u VREF %d\n", mux.kind, reg, 0x3ff, vref);
		reg = 0x3ff;
	}
	reg <<= shift;
//	printf("ADC to 10 bits %x shifted %d\n", reg, shift);
	avr->data[p->r_adcl] = reg;
	avr->data[p->r_adch] = reg >> 8;
	p->read_status = 1;
	return avr_core_watch_read(avr, addr);
}