Generating square wave signals using StartKit

If you have a simple question and just want an answer.
Post Reply
User avatar
HuyPham
New User
Posts: 2
Joined: Fri Feb 05, 2016 6:18 pm

Generating square wave signals using StartKit

Post by HuyPham »

Hello everyone,
I am a student and a newbie with XMOS MCU. Currently, I intend to drive several MA40S4S 40kHz ultrasonic transducers parralel. But firstly, I try to use XMOS StartKit to drive one. There are two questions I would like to ask and hope that you can help me:
1) Is the PWM the one that hep to generate square waves signals that might be used to input the transducers?
2) Is the Matlab simulink compatible with XMOS? Because the algorithms I want to do is like controlling the transducers with different phase delays and I think that MatLab could help model the algorithms to input to XMOS devices. Or you may give me some suggestion to do?

Thank for reading this,
Huy


henk
Respected Member
Posts: 347
Joined: Wed Jan 27, 2016 5:21 pm

Post by henk »

I don't know about the Matlab integration - somebody else may be able to help with that.

About running multiple phase-shifted 40-khz signal; a PWM software library may not be able to do that, but it is not difficult to program yourself. This generates 100 chirps of a 40 kHz signal:

Code: Select all

void forty(port p, unsigned short edge_clk_cnt) {
    for(int i = 0; i < 100; i++) {
        p @ edge_clk_cnt <: 1;
        edge_clk_cnt += 1250;
        p @ edge_clk_cnt <: 1;
        edge_clk_cnt += 1250;
    }
}
Each 'p @ edge_time' drives a 1 or a 0 at the specified count of clocks; by default each port is clocked of a 100 MHz reference clock, so 1250 clocks equals 12.5 us; twice that is 25 us which is the 1/40 kHz.

To generate four of them that are out of sync by 10 degrees each:

Code: Select all

#include <xs1.h>

port p0 = XS1_PORT_1E;
port p1 = XS1_PORT_1F;
port p2 = XS1_PORT_1G;
port p3 = XS1_PORT_1H;

main() {
  while(1) {
    unsigned short phase0 = (2500 * 0)/360;
    unsigned short phase1 = (2500 * 10)/360;
    unsigned short phase2 = (2500 * 20)/360;
    unsigned short phase3 = (2500 * 30)/360;
    unsigned int current;
    
    p0 <: 0 @ current;
    current += 5000;
    par {
        forty(p0, phase0 + current);
        forty(p1, phase1 + current);
        forty(p2, phase2 + current);
        forty(p3, phase3 + current);
    }
  }
}
The trick is to find out what the current clock count of one of the ports is before setting them all going. The statement "p <: 0 @ variable" stores the clock count at which the transition happens into variable. We then add 5,000 plus the phase difference as a starting point for each of the 100 chirps. 5,000 is more than enough time to start all threads, and then they will all start at their respective phase differences.

This scales up to eight transducers; by that time you will run out of threads. You can do many more transducers using wider ports, and by linking tiles together.
User avatar
HuyPham
New User
Posts: 2
Joined: Fri Feb 05, 2016 6:18 pm

Post by HuyPham »

Thank you very much @henk.
I'm trying to digest your explanation. BTW, could you send me any references that I should consider to read for generating these signals besides the XMOS documents?
User avatar
mon2
XCore Legend
Posts: 1913
Joined: Thu Jun 10, 2010 11:43 am
Contact:

Post by mon2 »

Have a review of this excellent tutorial using the startKit:

https://www.element14.com/community/gro ... e-programs
quyenhuynh
Member
Posts: 12
Joined: Thu Dec 22, 2016 9:36 am

Post by quyenhuynh »

Dear @henk, I also studying about this, please how to using wider ports as well as linking tiles together to this code can run with 50 transducers. Now, my code only operates with 8 transducers as you tutored that I attached following.
Thanks @henk very

Code: Select all

#include <xs1.h>

port p0 = XS1_PORT_1E;
port p1 = XS1_PORT_1F;
port p2 = XS1_PORT_1G;
port p3 = XS1_PORT_1H;
port p4 = XS1_PORT_1I;
port p5 = XS1_PORT_1J;
port p6 = XS1_PORT_1K;
port p7 = XS1_PORT_32A;
port p8 = XS1_PORT_1D;

void forty(port p, unsigned short edge_clk_cnt) {
    for(int i = 0; i < 100; i++) {
        p @ edge_clk_cnt <: 0;
        edge_clk_cnt += 1250;
        p @ edge_clk_cnt <: 1;
        edge_clk_cnt += 1250;
    }
}


int main(void) {
    while(1) {
        unsigned short phase0 = (2500 * 0)/360;
        unsigned short phase1 = (2500 * 10)/360;
        unsigned short phase2 = (2500 * 20)/360;
        unsigned short phase3 = (2500 * 30)/360;
        unsigned short phase4 = (2500 * 40)/360;
        unsigned short phase5 = (2500 * 50)/360;
        unsigned short phase6 = (2500 * 60)/360;
        unsigned short phase7 = (2500 * 70)/360;
        unsigned short phase8 = (2500 * 80)/360;



        unsigned int current;

            p0 <: 0 @ current;
            current += 5000;

            par {
                forty(p0, phase0 + current);
                forty(p1, phase1 + current);
                forty(p2, phase2 + current);
                forty(p3, phase3 + current);
                forty(p4, phase4 + current);
                forty(p5, phase5 + current);
                forty(p6, phase6 + current);
                forty(p7, phase7 + current);
                forty(p8, phase8 + current);
            }

                 }

    return 0;
}



Post Reply