How to use the ADC on StartKit?

All technical discussions and projects around startKIT
User avatar
infiniteimprobability
Verified
XCore Legend
Posts: 1145
Joined: Thu May 27, 2010 10:08 am

Post by infiniteimprobability »

Here you go all:

http://www.xcore.com/projects/adc-startkit

I have taken the low level code and wrapped it into a task with simple interfaces (trigger, read and a notification for conversion complete).

It triggers and samples all 4 channels each time and can either run continuously at a rate specified by you in microseconds, or converts each time a trigger command is sent.

The way the ADC works on the XS1-A devices is a bit different from a normal MCU (requires I/O trigger for each sample and connects over XMOS links) so the API is designed to abstract that all away.

I invested in lot of code comments in there, so if you want to modify the code to suit your needs, hopefully this will be straightforward.

Most importantly, it works on the startKIT regardless of whether you run over JTAG or boot from FLASH.

More info in adc.h, and the source itself.
User avatar
infiniteimprobability
Verified
XCore Legend
Posts: 1145
Joined: Thu May 27, 2010 10:08 am

Post by infiniteimprobability »

One other point.. -fxscope is still needed (or you have an xscope.config file in the project with xscope enabled, like the startKIT ADC example does). The reason for this is that it does extra link setup which is needed to get ADC packets across to the XTAG tile to the user tile.

There is no disadvantage to using -fxscope, and many will be using fast printing and/or real-time xscope anyhow which needs this switch, so there's no plan to change this. This ADC library is only for the startKIT and is due to the the special A8-Dev device we use which integrates XTAG. (although you could easily adapt it to run on non-startKIT platforms if you like by removing the link setup stuff)

We also have general libs for non-startKIT use such custom boards, sliceKIT, other boards etc. https://github.com/xcore/sc_a_series_support
or
https://github.com/xcore/sc_u_series_support
User avatar
Folknology
XCore Legend
Posts: 1274
Joined: Thu Dec 10, 2009 10:20 pm

Post by Folknology »

It would be good to add this to github/xcore perhaps to the existing Startkit examples.

regards
Al
User avatar
infiniteimprobability
Verified
XCore Legend
Posts: 1145
Joined: Thu May 27, 2010 10:08 am

Post by infiniteimprobability »

Agree - it should be part of the basic examples for sure. ADC is essential in many projects!

We will do this shortly.
User avatar
infiniteimprobability
Verified
XCore Legend
Posts: 1145
Joined: Thu May 27, 2010 10:08 am

Post by infiniteimprobability »

Done..

Have separated it out into a module (startkit_adc) for inclusion in your own app and an example app showing how to use it.

You can find it in the community tab (search for ADC) at the bottom left of the GUI, or clone it from https://github.com/xcore/sw_startkit_examples

Enjoy....
User avatar
Folknology
XCore Legend
Posts: 1274
Joined: Thu Dec 10, 2009 10:20 pm

Post by Folknology »

In the ADC server task first select you have:

Code: Select all

case i_adc.trigger():               //Start ADC state machine via interface method call
  if (adc_state == 0){
    adc_sample <: 1;                //Send first rising edge to trigger ADC
    t_trig_state :> trig_pulse_time;//Grab current time
    trig_pulse_time += ADC_TRIG_DELAY;//Setup trigger time for next edge (falling)
    adc_state = 1;                  //Start trigger state machine
  }
  else ; 
  break;
Could this also be written more intuitively this way:

Code: Select all

case !adc_state => i_adc.trigger():          //Start ADC state machine via interface method call
  adc_sample <: 1;                                //Send first rising edge to trigger ADC
  t_trig_state :> trig_pulse_time;             //Grab current time
  trig_pulse_time += ADC_TRIG_DELAY;   //Setup trigger time for next edge (falling)
  adc_state = 1;                                   //Start trigger state machine
  break;
i.e. using a state guard rather than an if, also is this any more efficient?
User avatar
infiniteimprobability
Verified
XCore Legend
Posts: 1145
Joined: Thu May 27, 2010 10:08 am

Post by infiniteimprobability »

Guarded event cases are a fantastic way of describing state machines and steering the transitions (and just add a few cycles before setting up the events to test for the guard), however in this case I always wanted i_adc.trigger() to respond (not block) to the client. Hence I put the test in the body of the case.

This way i_adc.trigger() doesn't ever block, and effectively just ignores the request if already in progress.
I thought this was more like how an MCU ADC works.

Open to changing this if a different behaviour makes more sense.
User avatar
Folknology
XCore Legend
Posts: 1274
Joined: Thu Dec 10, 2009 10:20 pm

Post by Folknology »

Ok thanks I should have studied you code a little deeper, it makes sense now.
MarcinMarecki
New User
Posts: 3
Joined: Thu Sep 05, 2013 2:20 pm

Post by MarcinMarecki »

Code: Select all

void sk_init_adc_network(void) {
	unsigned data;
	read_node_config_reg(tile[0], 0x87, data);
	if (data == 0) { 
		write_node_config_reg(tile[0], 0x85, 0xC0002004); // open
		write_node_config_reg(tile[0], 0x85, 0xC1002004); // and say hello


Is the "tile[0]" the same as the "adc_tile" in the line bellow:
startkit_adc.xc:36 write_periph_32(adc_tile, 2, 0x0, 1, data);  //Enable Ch 0

I'm also looking for docs for write_periph_32 function.

Regards,
Marcin
User avatar
infiniteimprobability
Verified
XCore Legend
Posts: 1145
Joined: Thu May 27, 2010 10:08 am

Post by infiniteimprobability »

[quote]

Code: Select all

void sk_init_adc_network(void) {
unsigned data;
read_node_config_reg(tile[0], 0x87, data);
if (data == 0) { 
write_node_config_reg(tile[0], 0x85, 0xC0002004); // open
write_node_config_reg(tile[0], 0x85, 0xC1002004); // and say hello


Is the "tile[0]" the same as the "adc_tile" in the line bellow:
startkit_adc.xc:36 write_periph_32(adc_tile, 2, 0x0, 1, data); //Enable Ch 0[/quote]
No - the code at the top (write_node_config) is setting up the links on the processor tile, so they can then talk to the peripheral tile (where the ADC is). This stuff is normally hidden in XC programming.  The tile definitions are in the .xn file. 
The write_periph_32(adc_tile... actually writes the remote register (in the adc/peripheral tile).

[quote]I'm also looking for docs for write_periph_32 function.
[/quote]
both write_node_config and write_periph_32 are deocumented in the xtimecomposer user guide. The link behaviour can be learned about here https://www.xmos.com/published/xsysteml