This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

How to implement VERY accurate delays

Other Parts Discussed in Thread: MSP430G2553

I want to implement very accurate delays with Tiva TM4C123H6PM uprocessor as is possible with msp430 series uprocessors with __delay_cycle(delayvalue) function (consumes precisely numbet of cycles in "hardware").

MSP430 document slau132i.pdf on page 125 informs that :

"
6.7.3 The __delay_cycle Intrinsic
The __delay_cycles intrinsic inserts code to consume precisely the number of specified cycles with no
side effects. The number of cycles delayed must be a compile-time constant.
"

I have consumed quite a long time on searching tiva c-series documents but I found only SysCtlDelay/ROM_SysCtlDelay functions  that I can use for delay purposes and seems that those functions are not implemented in "hardware level".

In fact my delays must be very accurate because morse character's dots, dashes and silent delays must be very accurate so that morse characters are recognized "by ear".

For example character B's morse responsible is "-...".

Dash's duration is 3 dots and lets say dot's duration in certain tranmission speed is 62 ms and silent delay between dots and dashes is 1 dot.

For example character B consists of hearable constant length sounds and constant length silent delays as :

beep(dash = 3 dots) = 3*62ms "-"
delay_silent(1 dot) = 62ms
beep(1 dot) = 62ms "."
delay_silent(1 dot) = 62ms
beep(1 dot) = 62ms
delay_silent(1 dot) = 62ms
beep(1 dot) = 62ms "."

As you can see the delays must be very accurate that morse characters do not mess up with each others. Morse character table can be found from here : http://en.wikipedia.org/wiki/Morse_code

Actually at the present time I have Stellaris LauchPad but seems that it is software and hardware compatible with Tiva C TM4C123G LaunchPad. Yes, I have ordered Tiva C LaunchPad.

So, how to implemet very accurate delays from software with Tiva C LauncPad's uController TM4C123G6PM?

  • Seeing that, "VERY Accurate Delays" title - thought for sure - this has to be X-Ray Diffraction or Gas Diffusion...

    Instead - Morse Code reincarnates!  Really - and you illustrate w/62mS as your constant length delay.  And I thought that punched tape - and RTTY - had died...

    Pardon - but some way/how - Morse Code and "VERY Accurate Delay" seems, "Oxymoron."  Decades (scores really) past -when dinosaurs and vacuum tubes ruled this earth - Morse Code, "lived/breathed."  And - to present qualification for this response - this reporter successfully received Morse Code - by ear - at 5, 13 and 20 WPM w/in NYC's "Federal Building."  (earning novice, general & extra-class license - later First Class Phone w/Radar - all by age 16)

    I'd wager very tall (but not well aligned) stack of chips that any of the Timers w/in this family of MCUs will prove "beyond adequate" for your Morse decode exercise.  The delays you seek are most robust and accurate when generated via any of the multiple Timers - not via the API function you list.  Indeed - timer-based delays make maximum use of the MCU's hardware - and may resolve to better than 1uS.

    I would challenge your use of any, "fixed" delay though.  It's been awhile but might the width of individual, "dits/dahs" change as the code rate varies?  I can't recall if alternatively - code range changes - impact only the inter-character time-spacing.  (i.e. they reduce as code speed increases)

    Recall that all NYC hams built their own electronic keyers - and simple "SOS" stream was ideal for determining both bit-time and code speed.  This same SOS should enable your MCU to "tune" its timing to the incoming, Morse code speed...

    Might morse code - like penmanship - checks - or driver-controlled vehicles - be following dinosaur footprints - to tall cliff?

  • Hello Pentti,

    The SysCtlDelay introduces 3 clock cycles of delay for upto 40MHz in Flash. Above 40Mhz number of clock cycles required to do the same must include 1 clock for branch and then 3 clock cycle for every execution. Considering that the delay expected is in ms, this would be accurate for the use scenario you have.

    Other than that if the requirement has to come down for every clock edge at 80MHz, then would suggest using a Timer Module.

    Regards

    Amit

  • Thank you cb1_mobile a lot of for your answer but unfortunatelly I do not understand your post very well, because my mother tongue - I am a finn.

    According on my calculations, when sending morse characters at speet 60 words  / minute, then dot's duration is around 62 ms.

                      dots    dashes

    A    .-            1        1
    B    -...        4        2
    C    -.-.        6        4
    D    -..            9        5
    E    .            10        5
    F    ..-.        13        6
    G    --.            14        8
    H    ....        18        8
    I    ..            20        8
    J    .---        21        11
    K    -.-            22        13
    L    .-..        25        14
    M    --            25        16
    N    .-            26        17
    O    ---            26        20
    P    .--.        28        22        
    Q    --.-        29        25
    R    .-.            31        26
    S    ...            34        26
    T    -            34        27
    U    ..-            36        29
    V    ...-        39        30
    X    -..-        41        33
    Y    -.--        42        36
    Z    --..        44        38
    Å    .--.-        46        40
    Ä    .-.-        48        42
    Ö    ...-        51        43

    1    .----        52        46
    2    ..---        54        49
    3    ...--        57        51    
    4    ....-        61        52
    5    .....        66        52
    6    -....        70        53
    7    --...        73        55
    8    ---..        75        58
    9    ----.        76        62
    0    -----        76        67

    average morse character consist of 76/38=2 dots
    average morse character consist of 67/38=1.76 dashes

  • "The SysCtlDelay introduces 3 clock cycles of delay for upto 40MHz in Flash"

    Thank you Amit Ashara for your answer on my question. Yes I have to consentrate uC's clocking frequences around 40 MHz in case to produce accurate delays.

  • So how to implement very accurate delays in this case (code is implemented for msp430 launchpad and is fully working if you connect loudspeaker with  1k resistor on the msp430's output pin as mentioned on the code.

    So I hope that someone "translates" this below code from msp430's envirnoment to tiva c's responsible launchapad's environmet. Keep in your mind that on specially the delay loop's implementation must be very strict liki in the boundaries of +-5%.

    Code is here :

    //mymorse1_code.c
    #include <msp430g2553.h>
    //#include <stdio.h>

    /*       total    dots    dashed
    A    .-            1        1
    B    -...        4        2
    C    -.-.        6        4
    D    -..            9        5
    E    .            10        5
    F    ..-.        13        6
    G    --.            14        8
    H    ....        18        8
    I    ..            20        8
    J    .---        21        11
    K    -.-            22        13
    L    .-..        25        14
    M    --            25        16
    N    .-            26        17
    O    ---            26        20
    P    .--.        28        22
    Q    --.-        29        25
    R    .-.            31        26
    S    ...            34        26
    T    -            34        27
    U    ..-            36        29
    V    ...-        39        30
    X    -..-        41        33
    Y    -.--        42        36
    Z    --..        44        38
    Å    .--.-        46        40
    Ä    .-.-        48        42
    Ö    ...-        51        43

    1    .----        52        46
    2    ..---        54        49
    3    ...--        57        51
    4    ....-        61        52
    5    .....        66        52
    6    -....        70        53
    7    --...        73        55
    8    ---..        75        58
    9    ----.        76        62
    0    -----        76        67

    average morse character consist of 76/38=2 dots
    average morse character consist of 67/38=1.76 dash

    Morse characters are sent on the air in 5 character groups :
    bfed6 ertyf ....

    If sending speed is 60 characters in minute, we have different kind
    of delays :

    1) average character consist of 2 dots and 1.76 dashes.
    Duration of dash is 3 times of dot duration
    Character duration = 2 + 3*1,76 =7,28 dots
    Delay between dot and dash is 1 dot -> Duration of whole
    character is 2 * 7,28 = 14,56 dots

    Example : b is -...

    - : 3 dots delay
    1 dot silent delay
    . : 1 dot delay
    1 dot silent delay
    . : 1 dot delay
    1 dot silent delay
    . : 1 dot delay
    3 dots delay after one whole morse character before next morse character

    Delay between 2 5 character groups is 1 dash :
    abcdef <1 dash silent delay> hijkl <1 dash silent delay>
    */

    //60 chrs/s
    //delay dot 62ms
    //delay dash 186 ms
    //delay beetween dot and dash and dot is 1 dot = 62ms
    //delay between 5 character groups is 3 dots = 1 dash = 186 ms

    //For example 60 chrs in a minute is 12 groups and each group 5 characters :
    // abxc3 5kosl bnf8e (12 pieces of 5 character gropus

    char morseTable[39][6] =
    {
        {'.', '-', '\0', ' ', ' ', ' '},        //a    aarne
        {'-', '.', '.', '.', '\0', ' '},        //b bertta
        {'-', '.', '-', '.', '\0', ' '},        //c celsius
        {'-', '.', '.', '\0', ' ', ' '},        //d daavid
        {'.', '\0', ' ', ' ', ' ', ' '},        //e eemeli
        {'.', '.', '-', '.', '\0', ' '},        //f farao
        {'-', '-', '.', '\0', ' ', ' '},        //g gideon
        {'.', '.', '.', '.', '\0', ' '},        //h heikki
        {'.', '.', '\0', ' ', ' ', ' '},        //i iivari
        {'.', '-', '-', '-', '\0', ' '},        //j jussi
        {'-', '.', '-', '\0', ' ', ' '},        //k kalle
        {'.', '-', '.', '.', '\0', ' '},        //l lauri
        {'-', '-', '\0', ' ', ' ', ' '},        //m matti
        {'-', '.', '\0', ' ', ' ', ' '},        //n niilo
        {'-', '-', '-', '\0', ' ', ' '},        //o otto
        {'.', '-', '-', '.', '\0', ' '},        //p paavo
        {'-', '-', '.', '-', '\0', ' '},        //q kuu
        {'.', '-', '.', '\0', ' ', ' '},        //r risto
        {'.', '.', '.', '\0', ' ', ' '},        //s sakari
        {'-', '\0', ' ', ' ', ' ', ' '},        //t tyyne
        {'.', '.', '-', '\0', ' ', ' '},        //u urho
        {'.', '.', '.', '-', '\0', ' '},        //v vihtori
        {'.', '-', '-', '\0', ' ', ' '},        //w viski
        {'-', '.', '.', '-', '\0', ' '},        //x äksä
        {'-', '.', '-', '-', '\0', ' '},        //y yrjö
        {'-', '-', '.', '.', '\0', ' '},        //z tseta
        {'.', '-', '-', '.', '-', '\0'},        //å åke
        {'.', '-', '.', '-', '\0', ' '},        //ä äiti
        {'-', '-', '-', '.', '\0', ' '},        //ö öljy
        {'-', '-', '-', '-', '-', '\0'},        //0
        {'.', '-', '-', '-', '-', '\0'},        //1
        {'.', '.', '-', '-', '-', '\0'},        //2
        {'.', '.', '.', '-', '-', '\0'},        //3
        {'.', '.', '.', '.', '-', '\0'},        //4
        {'.', '.', '.', '.', '.', '\0'},        //5
        {'-', '.', '.', '.', '.', '\0'},        //6
        {'-', '-', '.', '.', '.', '\0'},        //7
        {'-', '-', '-', '.', '.', '\0'},        //8
        {'-', '-', '-', '-', '.', '\0'},        //9
    };

    /*
    char telegram[160] = \
    "hjake kalle ghity fiddu dhalr xzert ghita kerwq jwdpr fadmv prkfj sfklw pawer \
    agkfn paore sjern zxcgd eufms wjfnf dhgod djxcn dlelg dkqax dkgld dpedk efipw\0";
    */



    char telegram[150] = \
    "sooni willb edone witht hetro ublyo fthew orlds \
    ooniw illbq donjw ithth etrou bleof thewo aaaaa\0";

    //mgoin ghome toliv ewith mylor dnomo rewee pinga \
    //ndwha lings ooniw illbe donee hfeyd eclod wepok\0";

    /*
    char telegram[150] = \
    "fffff fffff fffff fffff fffff fffff fffff fffff \
    fffff fffff fffff fffff fffff fffff fffff aaaaa\0";
    */

    #define aH 220 //note aH as 880 Hz -> 440 -> 220
    //#define dot 62*2  // -> 100 chr / min
    //#define dash 186*2 //-> 100 chr / min
    //#define dot 100 //120  chr/min
    //#define dash 300 //120 chr / min

    #define dot 150 //80 chr / min
    #define dash 450 //80 chr / min

    //#define dot 188 //60 chr / min
    //#define dash 564 //60 chr / min

    //#define dot 75


    void delay_ms(unsigned int ms )
    {
          unsigned int i;
          for (i = 0; i<= ms; i++)
            __delay_cycles(500); //Built-in function that suspends the execution for 500 cicles
    }

    void delay_us(unsigned int us )
    {
          unsigned int i;
          for (i = 0; i<= us/2; i++)
            __delay_cycles(1);
    }

    //This function generates the square wave that makes the piezo speaker sound at a determinated frequency.
    void beep(unsigned int note, unsigned int duration)
    {
        int i;
        long delay = (long)(10000/note);  //This is the semiperiod of each note.
        long time = (long)((duration*100)/(delay*2));  //This is how much time we need to spend on the note.
        for (i=0;i<time;i++)
        {
            P1OUT |= BIT4;             //Set P1.4...

            //Just for debugging .. a = 100
            int a = 100;
            a++;
            //End of debugging with a ...

            delay_us(delay);           //...for a semiperiod...
            P1OUT &= ~BIT4;            //...then reset it...
            delay_us(delay);           //...for the other semiperiod.
        }
        //delay_ms(20); //Add a little delay to separate the single notes
    }

    void ParseAndPlay()
    {
        int i = 0;
        int j = 0;
        char ch;
        for (i=0; i<95; i++)
        {
            ch = telegram[i];

            //Skipping space located in telegram table
            if (ch == ' ')
            {
                delay_ms(dot);
                delay_ms(dot);
                delay_ms(dot);
                delay_ms(dot);
                delay_ms(dot);
                //delay_ms(dot);
                //delay_ms(dot);
                continue;
            }
            ch = ch - 'a';
            j = 0;
            while (morseTable[ch][j] != '\0')
            {
                if (morseTable[ch][j] == '.')
                     beep(aH, dot);
                else
                    beep(aH, dash);

                delay_ms(dot);
                j++;
            }
            delay_ms(dash);
        }
    }//ParseAndPlay

    void main(void)
    {
          WDTCTL = WDTPW + WDTHOLD; //Disable Watchdog Timer
        P1DIR|=BIT4;              // P1.4 output

        while(1)
            ParseAndPlay();
        goto msgover;

        while(1)
        {
            int loops = 3;
            do
            {
            //Lets output 2 characters cq -> -.-. --.-
            //dash
            beep(aH, dash);
            delay_ms(dot);

            //dot
            beep(aH, dot);
            delay_ms(dot);

            //dash
            beep(aH, dash);
            delay_ms(dot);

            //dot
            beep(aH, dot);
            delay_ms(dash);
            //That was c

            //dash
            beep(aH, dash);
            delay_ms(dot);

            //dash
            beep(aH, dash);
            delay_ms(dot);

            //dot
            beep(aH, dot);
            delay_ms(dot);

            //dash
            beep(aH, dash);
            delay_ms(dash);
            //That was q

            delay_ms(dot);
            delay_ms(dot);
            delay_ms(dot);
            }
            while (--loops > 0);

            int innerLoop = 3;
            do
            {
                //de pena

                //d
                beep(aH, dash);
                delay_ms(dot);
                beep(aH, dot);
                delay_ms(dot);
                beep(aH, dot);
                delay_ms(dash);

                //e
                beep(aH, dot);
                delay_ms(dot);
                delay_ms(dash);

                //p
                beep(aH, dot);
                delay_ms(dot);
                beep(aH, dash);
                delay_ms(dot);
                beep(aH, dash);
                delay_ms(dot);
                beep(aH, dot);
                delay_ms(dash);

                //e
                beep(aH, dot);
                delay_ms(dash);

                //n
                beep(aH, dash);
                delay_ms(dot);
                beep(aH, dot);
                delay_ms(dash);

                //a
                beep(aH, dot);
                delay_ms(dot);
                beep(aH, dash);
                delay_ms(dash);


                delay_ms(dot);
                delay_ms(dot);
                delay_ms(dot);
            }
            while( --innerLoop > 0);
        }

    msgover:
    }//main



  • A Tiva implementation of msp430-style delay cycles can be found in BSPACM.  It uses the cycle counter so should be unaffected by clock speeds that increase wait states or the impact of compiler optimizations.  You will also need to enable the cycle counter; see the macros above the one the link sends you to.

    Also note that BSPACM uses the CMSIS headers that TI doesn't support; this thread on Stellarisiti includes similar code using driverlib headers.

  • For tiva i use System tick or the Hibernation moudule RTC to count time. So for a delay i just a while or a interupt with the RTC if i need to do alot of stuff at the same time