Total Hits: 771855
Past 7 days: 808 hits

Concurrent Blinkies

January 19, 2014 on 3:55 am | In Technology | No Comments

Now that we have a working, minimal, Hello World, its time to take it to the next level. This time, we’ll write a concurrent program that blinks two leds from two threads on two ports using two timers. Its twice the fun all around! 😛

Create a new project adding all the appropriate includes, or use the same one we created in the previous post. I’ll be using the same project modifying the code inside HelloWorld.xc. Lets take a quick look at the code:


#include<xs1.h>

out port p1 = XS1_PORT_1A;
out port p2 = XS1_PORT_1D;

timer t1, t2;

void blinky1(){
    unsigned int time;
    char state =0;

    t1 :> time;
    time += XS1_TIMER_MHZ * 1000* 300;
    while(1){
        t1 when timerafter(time) :> void;
        state = ~state;
        p1 <: state;
        time += XS1_TIMER_MHZ * 1000* 300;
    }
}

void blinky2(){
    unsigned int time;
    char state =0;

    t2 :> time;
    time += XS1_TIMER_MHZ * 1000* 200;
    while(1){
        t2 when timerafter(time) :> void;
        state = ~state;
        p2 <: state;
        time += XS1_TIMER_MHZ * 1000* 200;
    }
}

int main(void){
    par{
        blinky1();
        blinky2();
    }
}

We begin by including xs1.h, which enumerates the hardware resources on the XCore platform providing easy access to hardware resources; and also provides a lot of helper functions that simplify the setup and configuration of those hardware resources.

Page 10 of the XMOS StarterKit hardware manual says we have two little green user LEDs connected to two 1-bit ports (1A and 1D). Those are the little guys we’ll be blinking. In order to drive those leds, we’ll need to access the two ports to which they are connected. Since ports have to be declared as global variables in XC, we next declare our two ports for output:

out port p1 = XS1_PORT_1A;
out port p2 = XS1_PORT_1D;

The definitions for XS1_PORT_1A and XS1_PORT_1D come from xs1.h. XMOS was nice enough to enumerate all ports available on their XCore using simple, descriptive, names. They were also kind enough to make a table that lists all those names in a table included in their Introduction to XS1 Ports.

Since we’ll be blinking two leds on two separate threads, we’ll need a way to track time on each thread so we know when to turn on and off each led. Luckily for us, each XCore tile includes 10 timers we can use in our programs. For now, we’ll just declare a couple:

timer t1, t2;

Now, we come to our blinky thread functions. Lets have a look at the first one:

void blinky1(){
    unsigned int time;
    char state =0;

    t1 :> time;
    time += XS1_TIMER_MHZ * 1000* 300;
    while(1){
        t1 when timerafter(time) :> void;
        state = ~state;
        p1 <: state;
        time += XS1_TIMER_MHZ * 1000* 300;
    }
}

We begin by declaring an unsigned 32-bit integer called time that we’ll use to hold our time readings from timer t1. Since XC doesn’t provide a native boolean data type, we’ll use a char named state to hold our port state and set its initial state to zero. Then we read timer t1‘s state into time using an input construct (:>). Next, we increment the value of time by 300ms (XS1_TIMER_MHZ defines the clock speed in MHz at which the timer counts. We multiply this by 300,000 to ontain a 300ms cycle) and then we dive into an infinite loop.

The loop begins with a when statament that makes use of the timerafter() function. The conjunction of when and timerafter causes the input operation to wait until the timer reaches the value of time. Since we don’t care about the current value of the timer, we read that into void.

Next, we do a bitwise NOT operation on state to flip its bits before outputting its value to port p1. Note that only the most significant bit of state will actually be used since we are outputting to a 1-bit port.

Finally, we increment our time variable by the equivalent of another 300ms wait before repeating the loop again.

The second blinky function for the second thread is the same but uses timer t2 and has a cycle of 200ms instead.

The program concludes with its main function:

int main(void){
    par{
        blinky1();
        blinky2();
    }
}

The only thing we’re doing here is spawn blinky1 and blinky2 functions in two concurrent threads by calling them both inside a par statement.

Build the program in xTIMEcomposer by hitting CTRL-B and make sure there are no errors. Once it builds successfully, connect your StarterKit to your computer and hit CTRL-F11 to upload and run the program. If everything went successfully, your StarterKit should begin blinking its LEDs like this:

No Comments yet »

RSS feed for comments on this post. TrackBack URI

Leave a comment

You must be logged in to post a comment.


Powered by WordPress with Pool theme design by Borja Fernandez.
Entries and comments feeds. Valid XHTML and CSS. ^Top^
Free website monitoring service