TS-7250-V3 FPGA ADC

From embeddedTS Manuals

The TS-7250-V3 includes a simple low speed ADC to support the analog input on mikrobus modules.

  • 304hz sample rate
  • 8-bits resolution
  • 10kohm input impedance
  • 0-6V input range
  • 3% absolute accuracy

This ADC is accessed using the IIO subsystem. One time samples can be read from /sys/:

root@tsimx6:~# cat /sys/bus/iio/devices/iio\:device0/in_voltage0_raw 
127
root@tsimx6:~# cat /sys/bus/iio/devices/iio\:device0/in_voltage0_scale
25.781250000

The raw value is 0-255, and the scale value converts this to real world values. For example, 127*25.78125=3274.21875mV.

Faster samples, up to 304hz, are available using the buffer interface.

root@tsimx6:~# echo 1 > /sys/bus/iio/devices/iio\:device0/scan_elements/in_voltage0_en
root@tsimx6:~# iio_readdev iio:device0 | hexdump -C
WARNING: High-speed mode not enabled
00000000  80 00 00 00 00 00 00 00  4c a8 d9 e8 b7 33 83 15  |........L....3..|
00000010  7f 00 00 00 00 00 00 00  df 8f 22 e9 b7 33 83 15  |.........."..3..|
00000020  7f 00 00 00 00 00 00 00  b7 aa 55 e9 b7 33 83 15  |..........U..3..|
00000030  80 00 00 00 00 00 00 00  e9 d7 86 e9 b7 33 83 15  |.............3..|

In this case, column 1 that starts with 80 is the ADC value. Columns 2-8 are 0 padding. Columns 9-16 are the 64-bit ns timestamp. This is accurate to approximately 10us.

The ADC buffers can also be filled using libiio directly:

#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>
#include <assert.h>
#include <inttypes.h>
#include <iio.h>

static bool stop;
static void handle_sig(int sig)
{
	stop = true;
}

int main (int argc, char **argv)
{
	const struct iio_data_format *fmt;
	static struct iio_context *ctx;
	static struct iio_buffer *rxbuf;
	struct iio_channel *chn;
	struct iio_device *dev;

	/* Catch ctrl+c */
	signal(SIGINT, handle_sig);

	ctx = iio_create_default_context();
	assert(ctx);

	iio_context_set_timeout(ctx, 10000);

	assert(iio_context_get_devices_count(ctx) > 0);
	dev = iio_context_find_device(ctx, "50000180.mikro_adc");
	assert(dev);

	chn = iio_device_get_channel(dev, 0); /* voltage0 */
	assert(chn);

	iio_channel_enable(chn);
	fmt = iio_channel_get_data_format(chn);
	assert(fmt);

	rxbuf = iio_device_create_buffer(dev, 256, false);
	assert(rxbuf);

	printf("%s\n", iio_channel_get_id(chn));
	while (!stop) {
		ssize_t nbytes;
		uint8_t *dat;

		nbytes = iio_buffer_refill(rxbuf);
		if (nbytes < 0) {
			printf("Error refilling buf %d\n",(int) nbytes);
			break;
		}
		for (dat = iio_buffer_first(rxbuf, chn); 
			dat < (uint8_t *)iio_buffer_end(rxbuf);
			dat += iio_buffer_step(rxbuf)) {
			printf("%d\n", dat[0]);
			//printf("%.0f,\n", (float)dat[0] * fmt->scale);
		}
	}

	iio_buffer_destroy(rxbuf);
	iio_channel_disable(chn);
	iio_context_destroy(ctx);

	return 0;
}

For most users we recommend using the existing linux drivers, but the hardware core can be found at 0x50000180. It is a single 32-bit register:

Bits Reset value Description
31:24 0x55 Reserved
23:16 0x0 sample
15:3 0x0 Reserved
2 0 sample_missed [1]
1 0 sample_ready [2]
0 1 standby_en
  1. This means when the core updated sample_ready to 1, it was already 1. Cleared on read.
  2. Cleared on read