This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Function editor

Hello,

I'm currently using uVision 2.33. I've written the following function in the function editor to simulate an RC5 signal which I want to detect on P1.1:

define button "Start P1.1 Toggle", "p11_toggle()"
define button "Stop P1.1 Toggle" , "signal kill p11_toggle"

signal void Generate0()
{
    P1 &= ~0x02; /* pull T2EX(P1.1) low and generate interrupt */
    twatch( 889 );
    P1 |= 0x02;  /* pull T2EX(P1.1) high */
    twatch (889);
}

signal void Generate1()
{
    P1 |= 0x02;  /* pull T2EX(P1.1) high */
    twatch( 889 );
    P1 &= ~0x02; /* pull T2EX(P1.1) low and generate interrupt */
    twatch (889);
}

signal void p11_toggle()
{
    while (1)
    {
        // Bit1: start
        Generate1();
        // Bit2: indication
        Generate1();
        // Bit3: toggle
        Generate0();
        // Bit4: system5
        Generate0();
        // Bit5: system4
        Generate0();
        // Bit6: system3
        Generate0();
        // Bit7: system2
        Generate0();
        // Bit8: system1
        Generate1();
        // Bit9: command6
        Generate1();
        // Bit10: command5
        Generate0();
        // Bit11: command4
        Generate0();
        // Bit12: command3
        Generate0();
        // Bit13: command2
        Generate1();
        // Bit14: command1
        Generate0();
        swatch( 1 );
    }
}

If I compile this script, I don't get a compilation or warning from the function editor.

However, when I run my program and activate the toggling functionality on P1.1 via the button "Start P1.1 Toggle", I get the following error message:

*** function 'p11_toggle', error 99, line 27: signal() already activated
p11_toggle()
*** error 99: signal() already activated

I know that the functions Generate1() and Generate0() are called more than once without first killing and then re-calling them, but what is the alternative? How can I 'call' more than once the same function from within another function?

Also, when I put the funcions Generate1() and Generate0() at the end of the script, the compiler doesn't complain, but when I load this script, I get the following error:
*** error 34, line 9: undefined identifier

Why does the script compiler not inform me about this 'mistake'?

Rgds,

--Geert

  • When you call a signal function from within another signal function the debugger actually starts a separate "thread" of execution for the new signal function. In other words, the signal function you call runs separate from the calling signal.

    So, when the following code executes in p11_toggle:

            // Bit1: start
            Generate1();
            // Bit2: indication
            Generate1();
    

    it appears to the debugger that you start the Generate1 signal and then you immediately start the Generate1 signal. And, the error is generated.

    You need to add some wait time between these 2 calls. I modified your debugger functions to show what I mean.

    define button "Start P1.1 Toggle", "p11_toggle()"
    define button "Stop P1.1 Toggle" , "signal kill p11_toggle"
    
    signal void Generate0(void)
    {
    printf ("Gen0: %lu\n", states);
        P1 &= ~0x02; /* pull T2EX(P1.1) low and generate interrupt */
        twatch( 889 );
        P1 |= 0x02;  /* pull T2EX(P1.1) high */
        twatch (889);
    }
    
    signal void Generate1(void)
    {
    printf ("Gen1: %lu\n", states);
        P1 |= 0x02;  /* pull T2EX(P1.1) high */
        twatch( 889 );
        P1 &= ~0x02; /* pull T2EX(P1.1) low and generate interrupt */
        twatch (889);
    }
    
    signal void p11_toggle(void)
    {
        while (1)
        {
            // Bit1: start
            Generate1();
    twatch(2000);
            // Bit2: indication
            Generate1();
    twatch(2000);
            // Bit3: toggle
            Generate0();
    twatch(2000);
            // Bit4: system5
            Generate0();
    twatch(2000);
            // Bit5: system4
            Generate0();
    twatch(2000);
            // Bit6: system3
            Generate0();
    twatch(2000);
            // Bit7: system2
            Generate0();
    twatch(2000);
            // Bit8: system1
            Generate1();
    twatch(2000);
            // Bit9: command6
            Generate1();
    twatch(2000);
            // Bit10: command5
            Generate0();
    twatch(2000);
            // Bit11: command4
            Generate0();
    twatch(2000);
            // Bit12: command3
            Generate0();
    twatch(2000);
            // Bit13: command2
            Generate1();
    twatch(2000);
            // Bit14: command1
            Generate0();
    twatch(2000);
    
            swatch( 1 );
        }
    }
    

    I try to keep my signal functions completely contained, so I'd do this a little differently, but that's just a matter of personal taste.

    Jon

  • Jon,

    The problem is, if I add some extra wait time between to Generate calls, I don't comply with the RC standard anymore.

    As you can see in my script, the Generate0() and Generate1() functions have their own wait time. twatch( 889 ) (or a multipe of it) is exactly the RC5 standard time of a bi-phased pulse width, if the level (a 1 or a 0) doesn't change.
    With your improvements, I add immediately some time to it and the chance exists that I don't comply anymore with the RC5 standard.

    Since I also want to make my driver 'universal' (meaning in a later stage being able to automatically detect if the incoming signal is RC5 or RC6), things will result only in even smaller periods of time between two consecutive pulses.

    Any idea how to solve this issue?

    Rgds,

    --Geert

  • I can think of several ways to do this. The first one is a simple substitution. Just put the Generate0 and Generate1 functions in-line:


    /* Gen 0 on P1.1:  P1 &= ~0x02; twatch (889); P1 |= 0x02; twatch (889); */
    /* Gen 1 on P1.1:  P1 |= 0x02; twatch (889); P1 &= ~0x02; twatch (889); */
    
    
    signal void p11_toggle (void)
    {
    while (1)
      {
      // Bit1: start
      P1 |= 0x02; twatch (889); P1 &= ~0x02; twatch (889);
    
      // Bit2: indication
      P1 |= 0x02; twatch (889); P1 &= ~0x02; twatch (889);
    
      // Bit3: toggle
      P1 &= ~0x02; twatch (889); P1 |= 0x02; twatch (889);
    
      // Bit4: system5
      P1 &= ~0x02; twatch (889); P1 |= 0x02; twatch (889);
    
      // Bit5: system4
      P1 &= ~0x02; twatch (889); P1 |= 0x02; twatch (889);
    
      // Bit6: system3
      P1 &= ~0x02; twatch (889); P1 |= 0x02; twatch (889);
    
      // Bit7: system2
      P1 &= ~0x02; twatch (889); P1 |= 0x02; twatch (889);
    
      // Bit8: system1
      P1 |= 0x02; twatch (889); P1 &= ~0x02; twatch (889);
    
      // Bit9: command6
      P1 |= 0x02; twatch (889); P1 &= ~0x02; twatch (889);
    
      // Bit10: command5
      P1 &= ~0x02; twatch (889); P1 |= 0x02; twatch (889);
    
      // Bit11: command4
      P1 &= ~0x02; twatch (889); P1 |= 0x02; twatch (889);
    
      // Bit12: command3
      P1 &= ~0x02; twatch (889); P1 |= 0x02; twatch (889);
    
      // Bit13: command2
      P1 |= 0x02; twatch (889); P1 &= ~0x02; twatch (889);
    
      // Bit14: command1
      P1 &= ~0x02; twatch (889); P1 |= 0x02; twatch (889);
    
      swatch( 1 );
      }
    }
    

    The second way allows you to pass an unsigned integer containing the bits to send. A loop index scans the bits in the value and transmits the appropriate signal. Of course, I defaulted to a 14-bit value. However, if the length changes, you can simply pass the length to this function as well.

    signal void send_p11_info (unsigned int val)
    {
    unsigned char i;
    
    while (1)
      {
      for (i = 0; i < 14; i++)
        {
        if (val & (1 << i))   /* Send 1 */
          {
          P1 |= 0x02; twatch (889); P1 &= ~0x02; twatch (889);
          }
        else                  /* Send 0 */
          {
          P1 &= ~0x02; twatch (889); P1 |= 0x02; twatch (889);
          }
        }
    
      swatch( 1 );
      }
    }
    
    
    /*** Assign this function call to a button or whatever ***/
    
    send_p11_info (0x1183);
    
    
    /* 0x1183 = 01 0001 1000 0011 = the values transmitted by the original signal */
    

    Jon

  • The second one is a real nice solution. Thanks for this input, Jon!

    Rgds,

    --Geert