GPIO Operation Frequency

Hi Everyone,

Does anyone know wich is the Frequency of Operation of the GPIO?..I am working in an Aplication where the GPIOs should operate at a Frequency of 300 cycles per second (300 Hz) but I have made some proofs with my Fastrack Suprem 20 and all I got is a Frequency of just poor 20 Hz!!!..Does anyone know if I could change the Freqency of Operation?

I have looked into the documentation but I can not find this information anywhere!!! :confused:

Your help would be very much apreciated!!

Thanks in Advance…

How did you do that?

Remember, you can never get any predictable timing from any High-Level Language (HLL) such as ā€˜C’…

I made the proofs with an external pulse generator…This device is in the lab where I work and you can select a frequency …The problem is, that the Fasttrack Supreme 20 can not read it…The pulses are so fast that the modem just read some of them…So i decided to prove the capacity of the modem and I did so many tries until I found a capacity (frequency) of lecture of 20 Hz, so I was wondering if I could adjust that capacity cause it is very poor for the application that we are developing…

Open-AT is not suitable for directly reading or generating fast signals. You will need to add external hardware.

to illustrate. the minimum timer interval you can get using openAT (without using low-level interrupts) is 18.5 milliseconds (4 gsm frames)
even if you would use low level interrupts, you can’t use the gpio service.

where did you get that info Madouc?

It’s clearly stated in the ADL User Guide!

Hiya,

I did a small app that measured frequency using the ADL TCU API, and hardware interrupt pin 1 (GPIO 25).

I could read input frequencies up to about 30kHz reliably.

One issue was that the TCU could not deal with a Count Period of 1000mS (1 Sec) - why, I never worked out. I simply used a count period of 500mS and multiplied by 2…

Check out the TCU API doco, and the TCU sample. Note that this ONLY works on one of the hardware interrupt pins - not on general GPIO pins…

ciao, Dave

Thank you very much David, I will chek it out and I will comment my advances…

Really?? You do have something like that?? :open_mouth:
I’m working in something similar (frecuencies’ lectures in the GPIO’s) and would be very nice to see how it works. Is it possible to have a look at it???

… please :unamused:

Seeya
Dany_Q

There’s a couple of TCU examples in the SDK:

Sample - Signal Generator:

Sample - IRQ Measure

Sample - Signal Replica

Hi everyone,

I have been investigating and experimenting and I think that the best option could be the ā€œsignal_replica sampleā€, so I have compiled the sample with no modification and I have downloaded it to my fastrack Supreme 20, then I have introduced the comand ā€œAT+SIGNAL=1,21,1,1,1ā€ in order to monitorize the signal (first parameter—>1), The GPIO out is the GPIO21 (second parameter), the GPIO25 (INT1---->third parameter) is the entrance of the signal, it is operating in debounce mode (fourth parameter) and finally I gave the predeterminated value (1---->last parameter) of the debounce duration…

The problem is that the modem is not copying the signal, it is just generating a constant voltage, acoording to an external device wich measures the frequency. So, in first place I though it could be the external device (a problem of connection maybe) but it isn’t, I have checked it thousand of times and it is well connected and when I connect the signal of the signal generator directly to the the device wich measures the frequency, there is no problem, I just get the problem when I connect the signal supposely copied from the modem to the device.

Is there a special trick in this sample?
Am I giving the last two parameter wrong?---->I have observed that when give ā€œAT+SIGNAL=1,21,1,0,1ā€ The frequency device doesnt respond or the modem doesnt make anything, but when I give ā€œAT+SIGNAL=1,21,1,1,1ā€ the frequency device tells me that I am generating a constant signal…

I have also observed that I can change the last parameter (debounce duration) from 1 to 7 getting the same result in the frequency device, but it doesn’t work for the other values (0, 8-53)…could anyone explain me what a debounce process is and how could I choose a properly value for that?

Ok I have discarded the frequency meter and I have made a little modification to the sample Signal_replica…

/********************************************************************************************/
/*  signal_replica.c   -  Copyright Wavecom S.A. (c) 2002                                   */
/*                                                                                          */
/*                                                                                          */
/* DISCLAIMER OF WARRANTY                                                                   */
/* ======================                                                                   */
/* This Software is provided free of charge on an 'as is' basis. No warranty is given       */
/* by Wavecom S.A. in relation to the Software of the uses to which it may be put by you,   */
/* the user, or its merchantability, fitness or suitability for any particular purpose      */
/* or conditions; and/or that the use of the Software and all documentation relating        */
/* thereto by the Licensee will not infringe any third party copyright or other             */
/* intellectual property rights. Wavecom S.A. shall furthermore be under no obligation      */
/* to provide support of any nature for the Software and the Documentation.                 */
/*                                                                                          */
/* LIMIT OF LIABILITY                                                                       */
/* ==================                                                                       */
/* In no event shall Wavecom S.A. be liable for any loss or damages whatsoever or howsoever */
/* caused arising directly or indirectly in connection with this licence, the Software,     */
/* its use or otherwise except to the extent that such liability may not be lawfully        */
/* excluded. Notwithstanding the generality of the foregoing, Wavecom S.A. expressly        */
/* excludes liability for indirect, special, incidental or consequential loss or damage     */
/* which may arise in respect of the Software or its use, or in respect of other equipment  */
/* or property, or for loss of profit, business, revenue, goodwill or anticipated savings.  */
/*                                                                                          */
/********************************************************************************************/

/***************************************************************************/
/*  File       : signal_replica.c                                          */
/*-------------------------------------------------------------------------*/
/*  Object     : Customer application                                      */
/*                                                                         */
/*  contents   : Customer main procedures                                  */
/*                                                                         */
/*  Change     :                                                           */
/***************************************************************************/
/*
    $LogWavecom: G:\projet\mmi\pvcsarch\archives\open-mmi\SAMPLES\adl\New_Project\src\appli.c-arc $
 * --------------------------------------------------------------------------
 *  Date     | Author | Revision       | Description
 * ----------+--------+----------------+-------------------------------------
 *  25.10.05 | DPO    | 1.1            | * New V4 interface                 
 * ----------+--------+----------------+-------------------------------------
 *  16.12.02 | dpo    | 1.0            | Initial revision.                  
 * ----------+--------+----------------+-------------------------------------
*/

#include "adl_global.h"


/***************************************************************************/
/*  Mandatory variables                                                    */
/*-------------------------------------------------------------------------*/
/*  wm_apmCustomStackSize                                                  */
/*-------------------------------------------------------------------------*/
/***************************************************************************/
const u16 wm_apmCustomStackSize = 1024*3;
const u32 wm_apmIRQLowLevelStackSize =  1024;
const u32 wm_apmIRQHighLevelStackSize = 1024;



/***************************************************************************/
/*  Local variables                                                        */
/***************************************************************************/

// GPIO output to use
#define OUTPUT_GPIO_LABEL ( ADL_IO_GPIO | 0 )

// Commands strings
static const ascii * AtCmdStr_SIGNAL = "AT+SIGNAL";

// Interruption handle
static s32 MyIrqHandle;

// ExtInt service handle
static s32 MyExtIntHandle = ERROR;

// GPIO service handle
static s32 MyGpioHandle = ERROR;

// Signal generation mode
static bool signal_Mode;

// Signal output GPIO ID
static u8 signal_OutputIo = 1;
static u8 signal_OutputIoInnerID;

// Signal input pin
static adl_extintID_e signal_InputPin;

// Signal input filter
static adl_extintFilter_e signal_Filter;

// ExtInt Capabilities
static adl_extintCapabilities_t irq_ExtIntCapabilities;

// Signal debounce duration
static u8 signal_DebounceDuration = 1;

// ExtInt settings
adl_extintConfig_t signal_inputSettings;





/***************************************************************************/
/*  Local functions                                                        */
/***************************************************************************/



/****************************************************************************/
/*  Function   : MyIrqHandler                                               */
/*--------------------------------------------------------------------------*/
/*  Scope  : ADL Interruption service low level handler                     */
/*                                                                          */
/*  Return :  TRUE to enable High level handler notification                */
/*            FALSE to disable High level handler notification              */
/*                                                                          */
/*--------------------+---+---+---------------------------------------------*/
/*  Variable Name     |IN |OUT|  Use                                        */
/*--------------------+---+---+---------------------------------------------*/
/* Source             | X |   | Interruption source identifier              */
/*--------------------+---+---+---------------------------------------------*/
/* NotificationLevel  | X |   | Handler notification level                  */
/*--------------------+---+---+---------------------------------------------*/
/* Data               | X | X | Interruption event data structure           */
/*--------------------+---+---+---------------------------------------------*/
/****************************************************************************/
int counter=0;
static bool MyIrqHandler ( adl_irqID_e Source, adl_irqNotificationLevel_e NotificationLevel, adl_irqEventData_t * Data )
{

    s32 sReturn;
    adl_ioDefs_t Gpio_to_write = ADL_IO_GPIO | signal_OutputIoInnerID ;
    // WARNING: low level execution context
    TRACE (( 2, "IRQ interruption handler (Input: %d)", ( ( adl_extintInfo_t * ) Data->SourceData )->PinState ));
    
    // Check interruption edge
    if ( signal_inputSettings.Sensitivity == ADL_EXTINT_SENSITIVITY_RISING_EDGE )
    {
        // Rising edge: set output to 1
        sReturn = adl_ioWriteSingle ( MyGpioHandle, &Gpio_to_write, TRUE );
        counter++;
        // Reverse polarity
        signal_inputSettings.Sensitivity = ADL_EXTINT_SENSITIVITY_FALLING_EDGE;
    }
    else
    {
        // Falling edge: set output to 0
        sReturn = adl_ioWriteSingle ( MyGpioHandle, &Gpio_to_write, FALSE );
        
        // Reverse polarity
        signal_inputSettings.Sensitivity = ADL_EXTINT_SENSITIVITY_RISING_EDGE;
    }
    if ( sReturn < 0 )
        TRACE (( 2, "adl_ioWriteSingle GPIO %d : %d error %X ",signal_OutputIoInnerID, sReturn , Gpio_to_write & ADL_IO_ERR_MSK ));
    
    // Re-configure to reverse polarity
    adl_extintConfig ( MyExtIntHandle, &signal_inputSettings );
    
    return FALSE;
}

void my_function(u8 ID, void * Context){
	ascii *myMsg;

	                       myMsg = adl_memGet(sizeof(ascii)*128);    // allocate memory for string
	                       myMsg[0] = 0x00;                                      // ensure string starts with 'NUL'

	                    wm_sprintf(myMsg, "Value of Counter is %d", counter);

	                       adl_atSendResponse(ADL_AT_RSP, myMsg);
	                        adl_memRelease(myMsg);
                            counter=0;
}

/****************************************************************************/
/*  Function   : MyControlCommandHandler                                    */
/*--------------------------------------------------------------------------*/
/*  Scope  : AT+SIGNAL command handler                                      */
/*                                                                          */
/*  Return : VOID                                                           */
/*                                                                          */
/*--------------------+---+---+---------------------------------------------*/
/*  Variable Name     |IN |OUT|  Use                                        */
/*--------------------+---+---+---------------------------------------------*/
/* params             | X |   | Incoming AT command parameters              */
/*--------------------+---+---+---------------------------------------------*/
/****************************************************************************/
static void MyControlCommandHandler ( adl_atCmdPreParser_t * params )
{
    ascii RspStr [ 80 ];

    // Switch on command type
    switch ( params->Type )
    {
        // Test command
        case ADL_CMD_TYPE_TEST :
            wm_sprintf ( RspStr, "\r\n%s: (0-1),(0-%d),(0-%d),(0-%d),(0-%d)\r\n", AtCmdStr_SIGNAL + 2, ADL_IO_NUM_MSK, irq_ExtIntCapabilities.NbExternalInterrupt - 1, irq_ExtIntCapabilities.DebounceMode , irq_ExtIntCapabilities.MaxDebounceDuration - 1);
            adl_atSendResponsePort ( ADL_AT_RSP, params->Port, RspStr );
            adl_atSendStdResponsePort ( ADL_AT_RSP, params->Port, ADL_STR_OK );
        break;
        
        // Read command
        case ADL_CMD_TYPE_READ :
            wm_sprintf ( RspStr, "\r\n%s: %d,%d,%d,%d,%d\r\n", AtCmdStr_SIGNAL + 2, signal_Mode, signal_OutputIo, signal_InputPin, signal_Filter, signal_DebounceDuration );
            adl_atSendResponsePort ( ADL_AT_RSP, params->Port, RspStr );
            adl_atSendStdResponsePort ( ADL_AT_RSP, params->Port, ADL_STR_OK );
        break;
        
        // Parameters command
        case ADL_CMD_TYPE_PARA :
        {
            // Analyses parameters
            ascii * P0 = ADL_GET_PARAM ( params, 0 ),
                  * P1 = ADL_GET_PARAM ( params, 1 ),
                  * P2 = ADL_GET_PARAM ( params, 2 ),
                  * P3 = ADL_GET_PARAM ( params, 3 ),
                  * P4 = ADL_GET_PARAM ( params, 4 );
            u8 iP0, iP1;
            s32 sReturn;
            
            // Check Parameters
            if ( !P0
              // Mode
              || ( ( iP0 = wm_atoi ( P0 ) ) > 1 )
              // Output IO ID
              || ( P1
                && ( ( ( iP1 = wm_atoi ( P1 ) ) < 1 )
                  || ( iP1 > ADL_IO_NUM_MSK)
                   )
                 )
               )
            {
                // Syntax error
                adl_atSendStdResponseExtPort ( ADL_AT_RSP, params->Port, ADL_STR_CME_ERROR, 3 );
            }
            else
            {
                // Check if signal is running
                if ( signal_Mode )
                {
                    // Unsubscribe from ExtInt service
                    sReturn = adl_extintUnsubscribe ( MyExtIntHandle );
                    MyExtIntHandle = ERROR;
                    TRACE (( 1, "Unsubscribe from ExtInt: %d", sReturn ));
                    
                    // Unsubscribe from GPIO
                    sReturn = adl_ioUnsubscribe ( MyGpioHandle );
                    MyGpioHandle = ERROR;
                    TRACE (( 1, "Unsubscribe from GPIO %d: %d", signal_OutputIo, sReturn ));
                }
                
                // Update signal mode
                signal_Mode = iP0;
                TRACE (( 1, "New signal mode: %d", signal_Mode ));
                
                // Check for mode
                if ( signal_Mode )
                {
                    // GPIO 0 by default
                    adl_ioDefs_t GpioConfig = OUTPUT_GPIO_LABEL | ADL_IO_DIR_OUT | ADL_IO_LEV_LOW ;

                    // Set input pin (if supplied)
                    if ( P2 )
                    {
                        signal_InputPin = wm_atoi ( P2 );
                    }
                    // Set input process (if supplied)
                    if ( P3 )
                    {
                        signal_Filter = wm_atoi ( P3 );
                    }
                    // Set debounce duration (if supplied)
                    if ( P4 )
                    {
                        signal_DebounceDuration = wm_atoi ( P4 );
                    }
                    
                    // Fill IO settings, according to desired value (if supplied)
                    if ( P1 )
                    {
                        signal_OutputIoInnerID = iP1;
                    }
                    GpioConfig = GpioConfig | signal_OutputIoInnerID ;
                    TRACE (( 1, "GPIO ID for current product: %d", signal_OutputIoInnerID ));
                    
                    // Subscribe IO
                    MyGpioHandle = adl_ioSubscribe ( 1, &GpioConfig, 0, 0, 0 );
                    TRACE (( 1, "Subscribe to GPIO: %d", MyGpioHandle ));
                    
                    // Check if subscription is OK
                    if ( MyGpioHandle >= 0 )
                    {
                        // Remember GPIO id
                        signal_OutputIo = iP1;
                        
                        // Fill ExtInt settings, according to the supplied ones
                        signal_inputSettings.Sensitivity = ADL_EXTINT_SENSITIVITY_RISING_EDGE;
                        signal_inputSettings.Filter = signal_Filter;
                        signal_inputSettings.FilterDuration = signal_DebounceDuration;
                        TRACE (( 1, "Input process %d; debounce duration %d", signal_Filter, signal_DebounceDuration ));
                        
                        // Subscribe to the ExtInt service
                        MyExtIntHandle = adl_extintSubscribe ( signal_InputPin, MyIrqHandle, 0, &signal_inputSettings );
                        TRACE (( 1, "Subscribe to ExtInt (%d): %d", signal_InputPin, MyExtIntHandle ));
                        
                        // Check if subscription is OK
                        if ( MyExtIntHandle >= 0 )
                        {
                            // OK...
                            adl_atSendStdResponsePort ( ADL_AT_RSP, params->Port, ADL_STR_OK );
                        }
                        else
                        {
                            // Reset state
                            signal_Mode = FALSE;
                            
                            // ExtInt Subscription error
                            adl_atSendStdResponseExtPort ( ADL_AT_RSP, params->Port, ADL_STR_CME_ERROR, 3 );
                        }
                    }
                    else
                    {
                        // Reset state
                        signal_Mode = FALSE;
                        
                        // GPIO Subscription error
                        adl_atSendStdResponseExtPort ( ADL_AT_RSP, params->Port, ADL_STR_CME_ERROR, 3 );
                    }
                }
                else
                {
                    // Nothing to do
                    adl_atSendStdResponsePort ( ADL_AT_RSP, params->Port, ADL_STR_OK );
                }
            }
        }
        break;
    }
}



/***************************************************************************/
/*  Function   : adl_main                                                  */
/*-------------------------------------------------------------------------*/
/*  Object     : Customer application initialisation                       */
/*                                                                         */
/*-------------------------------------------------------------------------*/
/*  Variable Name     |IN |OUT|GLB|  Utilisation                           */
/*--------------------+---+---+---+----------------------------------------*/
/*  InitType          |   |   |   |  Application start mode reason         */
/*--------------------+---+---+---+----------------------------------------*/
/***************************************************************************/
void adl_main ( adl_InitType_e InitType )
{
    TRACE (( 1, "Signal Replica Sample: Main" ));
    
    // Interruption & message handlers definition
    MyIrqHandle  = adl_irqSubscribe ( MyIrqHandler, ADL_IRQ_NOTIFY_LOW_LEVEL, ADL_IRQ_PRIORITY_HIGH_LEVEL, ADL_IRQ_OPTION_AUTO_READ );
    TRACE (( 1, "Interruption handler subscription: %d", MyIrqHandle ));
    TRACE (( 1, "Application context diagnostic: %X", adl_ctxGetDiagnostic() ));

    // Get ExtInt Capabilties
    adl_extintGetCapabilities( &irq_ExtIntCapabilities );
        
    // Subscribe to start/stop command if all is OK for IRQ subscription
    if ( MyIrqHandle >= OK )
    {
        // Subscribe to the control command
        adl_atCmdSubscribe ( AtCmdStr_SIGNAL, MyControlCommandHandler, ADL_CMD_TYPE_TEST | ADL_CMD_TYPE_READ | ADL_CMD_TYPE_PARA | 0x51 );

    }
    else if ( MyIrqHandle == ADL_RET_ERR_NOT_SUPPORTED )
    {
        // Feature not enabled
        adl_atSendResponse ( ADL_AT_UNS, "\r\nInit Failed; Real Time enhancement feature not enabled.\r\n" );
    }
    adl_tmrSubscribe ( TRUE, 600, ADL_TMR_TYPE_100MS, my_function );

}

The program works fine when I give an input signal of 2.7 V pp and 0.25 Hz or less but If I give a higher frecuency (for example 0.5 Hz, 1Hz, etc) it doesnt copy the squared wave…why???

I thought it could handle waves of 500 Hz!!! I have tried to activate manually the interruptions with the following command…

ā€œAT+WIPC=1,ā€œINT1ā€,0,0ā€ and after that I run the application but it still behaves like before…I have also reseted the modem wit ā€œAT+CFUN=1ā€ā€¦but nothing happens…

Should I probe another commands?
Does anyone know how could I activate the INTERRUPTIONS?

Hiya,

I haven’t run up your code, but there are a couple of things to check.

  • I/O level on the Fastrack Supreme is max 2V8. Any more than that and you’ve let the smoke out of your device. The Wavecom modules are NOT at all forgiving of overvoltages.
  • Some of the TCU functions require the Real Time commercial feature to be enabled on your modem. Please check the AT command guide for decoding the results of AT+WCFM=5

Also, I’m now a bit confused about what you are trying to achieve. Can you explain again your aims and maybe we can help some more.

ciao, Dave

Note that the Traces from interrupt handlers come on different ā€œflowsā€ from the main application.

This caught me out the 1st time I used interrupt handlers: I thought they weren’t working, because I was seeing no traces - but that was just because I was looking in the wrong place! :blush:

See: viewtopic.php?f=21&t=3462&p=15429&hilit=llh+hlh#p15429

Also, for this kind of work, you really need an Oscilloscope to see what’s going on…

Hiya,

In particular, for at least R7.3/7.4 the Low level interrupt traces are on LLH, and high level interrupt traces are on HLH.

Note too that it’s not a good idea to have too many trace statements in tha Low Level interrupts, as these tend to be time crititcal and the TRACE() macros can slow things down.

ciao, Dave

Note that this is documented in the ADL User Guide! :smiley:

Agreed!
In general, one should always minimise what’s done in any interrupt handler - and be particularly cautious of any ā€œtime-consumingā€ activity…!

Ok, yesterday I could solve the problem…

The pulse generator that we have at work is operated by mechanical relays and unfortunately I do not have an oscilloscope in here…Based on that, I thought it would be better to have a pulse generator operated by solid state relays, but I have two wavecom fastrack supreme 20 modems and I got an idea…

I decided to download the signal_generator sample in one of the modems and in the other modem, I have downloaded the signal_replica sample.

I checked out the code of the sample_generator and I modified it, in order it could generate waves of 300 Hz. Once I made the modifications, I have read the signal with the frequency meter and the frequency was of course 300 Hz!!! After that, I connected the two modems. One modem would generate the signal and the other would copy it. In order to be sure of that, I have connected the frequency meter to the modem wich copies the signal and EUREKA!!! it worked!!!

Now I am going to share both codes and maybe you could helpme out with another little problem that I have…

The program of replica should count the amount of pulses every 24 hours and then I should receive a file with that information trouhg the FTP Service (that is not the problem because I have made apliccations with that servive).

As you are going to see, I have programmed the signal_replica code to give an advice every minute instead of every 24 hours (it is just an experiment, not the final code, of course…) and it seems it is working but most of time I receive the message 2 minutes later instead of 1 minute, so there is a delay of time and I would like it were instantaneous.

I have been thinking and I got the conclusion that it behaves like that due to the interruption routine. I mean, The Interruption routine has a priority over the main program and due to the high frequency (300 Hz) I do not receive the message on time and I should, at least for this application that I am developing…

Could anyone check the program of signal_replica that I have made and tell me what could I do in order to receive the message on time?

here is the code for the signal_replica sample…

/********************************************************************************************/
/*  signal_replica.c   -  Copyright Wavecom S.A. (c) 2002                                   */
/*                                                                                          */
/*                                                                                          */
/* DISCLAIMER OF WARRANTY                                                                   */
/* ======================                                                                   */
/* This Software is provided free of charge on an 'as is' basis. No warranty is given       */
/* by Wavecom S.A. in relation to the Software of the uses to which it may be put by you,   */
/* the user, or its merchantability, fitness or suitability for any particular purpose      */
/* or conditions; and/or that the use of the Software and all documentation relating        */
/* thereto by the Licensee will not infringe any third party copyright or other             */
/* intellectual property rights. Wavecom S.A. shall furthermore be under no obligation      */
/* to provide support of any nature for the Software and the Documentation.                 */
/*                                                                                          */
/* LIMIT OF LIABILITY                                                                       */
/* ==================                                                                       */
/* In no event shall Wavecom S.A. be liable for any loss or damages whatsoever or howsoever */
/* caused arising directly or indirectly in connection with this licence, the Software,     */
/* its use or otherwise except to the extent that such liability may not be lawfully        */
/* excluded. Notwithstanding the generality of the foregoing, Wavecom S.A. expressly        */
/* excludes liability for indirect, special, incidental or consequential loss or damage     */
/* which may arise in respect of the Software or its use, or in respect of other equipment  */
/* or property, or for loss of profit, business, revenue, goodwill or anticipated savings.  */
/*                                                                                          */
/********************************************************************************************/

/***************************************************************************/
/*  File       : signal_replica.c                                          */
/*-------------------------------------------------------------------------*/
/*  Object     : Customer application                                      */
/*                                                                         */
/*  contents   : Customer main procedures                                  */
/*                                                                         */
/*  Change     :                                                           */
/***************************************************************************/
/*
    $LogWavecom: G:\projet\mmi\pvcsarch\archives\open-mmi\SAMPLES\adl\New_Project\src\appli.c-arc $
 * --------------------------------------------------------------------------
 *  Date     | Author | Revision       | Description
 * ----------+--------+----------------+-------------------------------------
 *  25.10.05 | DPO    | 1.1            | * New V4 interface                 
 * ----------+--------+----------------+-------------------------------------
 *  16.12.02 | dpo    | 1.0            | Initial revision.                  
 * ----------+--------+----------------+-------------------------------------
*/

#include "adl_global.h"


/***************************************************************************/
/*  Mandatory variables                                                    */
/*-------------------------------------------------------------------------*/
/*  wm_apmCustomStackSize                                                  */
/*-------------------------------------------------------------------------*/
/***************************************************************************/
const u16 wm_apmCustomStackSize = 1024*3;
const u32 wm_apmIRQLowLevelStackSize =  1024;
const u32 wm_apmIRQHighLevelStackSize = 1024;



/***************************************************************************/
/*  Local variables                                                        */
/***************************************************************************/

// GPIO output to use
#define OUTPUT_GPIO_LABEL ( ADL_IO_GPIO | 0 )

// Commands strings
static const ascii * AtCmdStr_SIGNAL = "AT+SIGNAL";

// Interruption handle
static s32 MyIrqHandle;

// ExtInt service handle
static s32 MyExtIntHandle = ERROR;

// GPIO service handle
static s32 MyGpioHandle = ERROR;

// Signal generation mode
static bool signal_Mode;

// Signal output GPIO ID
static u8 signal_OutputIo = 1;
static u8 signal_OutputIoInnerID;

// Signal input pin
static adl_extintID_e signal_InputPin;

// Signal input filter
static adl_extintFilter_e signal_Filter;

// ExtInt Capabilities
static adl_extintCapabilities_t irq_ExtIntCapabilities;

// Signal debounce duration
static u8 signal_DebounceDuration = 1;

// ExtInt settings
adl_extintConfig_t signal_inputSettings;





/***************************************************************************/
/*  Local functions                                                        */
/***************************************************************************/



/****************************************************************************/
/*  Function   : MyIrqHandler                                               */
/*--------------------------------------------------------------------------*/
/*  Scope  : ADL Interruption service low level handler                     */
/*                                                                          */
/*  Return :  TRUE to enable High level handler notification                */
/*            FALSE to disable High level handler notification              */
/*                                                                          */
/*--------------------+---+---+---------------------------------------------*/
/*  Variable Name     |IN |OUT|  Use                                        */
/*--------------------+---+---+---------------------------------------------*/
/* Source             | X |   | Interruption source identifier              */
/*--------------------+---+---+---------------------------------------------*/
/* NotificationLevel  | X |   | Handler notification level                  */
/*--------------------+---+---+---------------------------------------------*/
/* Data               | X | X | Interruption event data structure           */
/*--------------------+---+---+---------------------------------------------*/
/****************************************************************************/
int counter;
static bool MyIrqHandler ( adl_irqID_e Source, adl_irqNotificationLevel_e NotificationLevel, adl_irqEventData_t * Data )
{

    s32 sReturn;
    adl_ioDefs_t Gpio_to_write = ADL_IO_GPIO | signal_OutputIoInnerID ;
    // WARNING: low level execution context
    TRACE (( 2, "IRQ interruption handler (Input: %d)", ( ( adl_extintInfo_t * ) Data->SourceData )->PinState ));
    
    // Check interruption edge
    if ( signal_inputSettings.Sensitivity == ADL_EXTINT_SENSITIVITY_RISING_EDGE )
    {
        // Rising edge: set output to 1
        sReturn = adl_ioWriteSingle ( MyGpioHandle, &Gpio_to_write, TRUE );
        counter++;
        // Reverse polarity
        signal_inputSettings.Sensitivity = ADL_EXTINT_SENSITIVITY_FALLING_EDGE;
    }
    else
    {
        // Falling edge: set output to 0
        sReturn = adl_ioWriteSingle ( MyGpioHandle, &Gpio_to_write, FALSE );
        
        // Reverse polarity
        signal_inputSettings.Sensitivity = ADL_EXTINT_SENSITIVITY_RISING_EDGE;
    }
    if ( sReturn < 0 )
        TRACE (( 2, "adl_ioWriteSingle GPIO %d : %d error %X ",signal_OutputIoInnerID, sReturn , Gpio_to_write & ADL_IO_ERR_MSK ));
    
    // Re-configure to reverse polarity
    adl_extintConfig ( MyExtIntHandle, &signal_inputSettings );
    
    return FALSE;
}
int copia;
void my_function(u8 ID, void * Context){
	copia=counter;
	counter=0;

	ascii *myMsg;

	                       myMsg = adl_memGet(sizeof(ascii)*128);    // allocate memory for string
	                       myMsg[0] = 0x00;                                      // ensure string starts with 'NUL'

	                    wm_sprintf(myMsg, "Value of Counter is %d", copia);

	                       adl_atSendResponse(ADL_AT_RSP, myMsg);
	                        adl_memRelease(myMsg);

}

void my_function2(u8 ID, void * Context){
	adl_atCmdCreate("AT+SIGNAL=1,21,1,0,1",ADL_AT_PORT_TYPE(ADL_PORT_UART1, TRUE), (adl_atRspHandler_t)NULL, NULL);

}

/****************************************************************************/
/*  Function   : MyControlCommandHandler                                    */
/*--------------------------------------------------------------------------*/
/*  Scope  : AT+SIGNAL command handler                                      */
/*                                                                          */
/*  Return : VOID                                                           */
/*                                                                          */
/*--------------------+---+---+---------------------------------------------*/
/*  Variable Name     |IN |OUT|  Use                                        */
/*--------------------+---+---+---------------------------------------------*/
/* params             | X |   | Incoming AT command parameters              */
/*--------------------+---+---+---------------------------------------------*/
/****************************************************************************/
static void MyControlCommandHandler ( adl_atCmdPreParser_t * params )
{
    ascii RspStr [ 80 ];

    // Switch on command type
    switch ( params->Type )
    {
        // Test command
        case ADL_CMD_TYPE_TEST :
            wm_sprintf ( RspStr, "\r\n%s: (0-1),(0-%d),(0-%d),(0-%d),(0-%d)\r\n", AtCmdStr_SIGNAL + 2, ADL_IO_NUM_MSK, irq_ExtIntCapabilities.NbExternalInterrupt - 1, irq_ExtIntCapabilities.DebounceMode , irq_ExtIntCapabilities.MaxDebounceDuration - 1);
            adl_atSendResponsePort ( ADL_AT_RSP, params->Port, RspStr );
            adl_atSendStdResponsePort ( ADL_AT_RSP, params->Port, ADL_STR_OK );
        break;
        
        // Read command
        case ADL_CMD_TYPE_READ :
            wm_sprintf ( RspStr, "\r\n%s: %d,%d,%d,%d,%d\r\n", AtCmdStr_SIGNAL + 2, signal_Mode, signal_OutputIo, signal_InputPin, signal_Filter, signal_DebounceDuration );
            adl_atSendResponsePort ( ADL_AT_RSP, params->Port, RspStr );
            adl_atSendStdResponsePort ( ADL_AT_RSP, params->Port, ADL_STR_OK );
        break;
        
        // Parameters command
        case ADL_CMD_TYPE_PARA :
        {
            // Analyses parameters
            ascii * P0 = ADL_GET_PARAM ( params, 0 ),
                  * P1 = ADL_GET_PARAM ( params, 1 ),
                  * P2 = ADL_GET_PARAM ( params, 2 ),
                  * P3 = ADL_GET_PARAM ( params, 3 ),
                  * P4 = ADL_GET_PARAM ( params, 4 );
            u8 iP0, iP1;
            s32 sReturn;
            
            // Check Parameters
            if ( !P0
              // Mode
              || ( ( iP0 = wm_atoi ( P0 ) ) > 1 )
              // Output IO ID
              || ( P1
                && ( ( ( iP1 = wm_atoi ( P1 ) ) < 1 )
                  || ( iP1 > ADL_IO_NUM_MSK)
                   )
                 )
               )
            {
                // Syntax error
                adl_atSendStdResponseExtPort ( ADL_AT_RSP, params->Port, ADL_STR_CME_ERROR, 3 );
            }
            else
            {
                // Check if signal is running
                if ( signal_Mode )
                {
                    // Unsubscribe from ExtInt service
                    sReturn = adl_extintUnsubscribe ( MyExtIntHandle );
                    MyExtIntHandle = ERROR;
                    TRACE (( 1, "Unsubscribe from ExtInt: %d", sReturn ));
                    
                    // Unsubscribe from GPIO
                    sReturn = adl_ioUnsubscribe ( MyGpioHandle );
                    MyGpioHandle = ERROR;
                    TRACE (( 1, "Unsubscribe from GPIO %d: %d", signal_OutputIo, sReturn ));
                }
                
                // Update signal mode
                signal_Mode = iP0;
                TRACE (( 1, "New signal mode: %d", signal_Mode ));
                
                // Check for mode
                if ( signal_Mode )
                {
                    // GPIO 0 by default
                    adl_ioDefs_t GpioConfig = OUTPUT_GPIO_LABEL | ADL_IO_DIR_OUT | ADL_IO_LEV_LOW ;

                    // Set input pin (if supplied)
                    if ( P2 )
                    {
                        signal_InputPin = wm_atoi ( P2 );
                    }
                    // Set input process (if supplied)
                    if ( P3 )
                    {
                        signal_Filter = wm_atoi ( P3 );
                    }
                    // Set debounce duration (if supplied)
                    if ( P4 )
                    {
                        signal_DebounceDuration = wm_atoi ( P4 );
                    }
                    
                    // Fill IO settings, according to desired value (if supplied)
                    if ( P1 )
                    {
                        signal_OutputIoInnerID = iP1;
                    }
                    GpioConfig = GpioConfig | signal_OutputIoInnerID ;
                    TRACE (( 1, "GPIO ID for current product: %d", signal_OutputIoInnerID ));
                    
                    // Subscribe IO
                    MyGpioHandle = adl_ioSubscribe ( 1, &GpioConfig, 0, 0, 0 );
                    TRACE (( 1, "Subscribe to GPIO: %d", MyGpioHandle ));
                    
                    // Check if subscription is OK
                    if ( MyGpioHandle >= 0 )
                    {
                        // Remember GPIO id
                        signal_OutputIo = iP1;
                        
                        // Fill ExtInt settings, according to the supplied ones
                        signal_inputSettings.Sensitivity = ADL_EXTINT_SENSITIVITY_RISING_EDGE;
                        signal_inputSettings.Filter = signal_Filter;
                        signal_inputSettings.FilterDuration = signal_DebounceDuration;
                        TRACE (( 1, "Input process %d; debounce duration %d", signal_Filter, signal_DebounceDuration ));
                        
                        // Subscribe to the ExtInt service
                        MyExtIntHandle = adl_extintSubscribe ( signal_InputPin, MyIrqHandle, 0, &signal_inputSettings );
                        TRACE (( 1, "Subscribe to ExtInt (%d): %d", signal_InputPin, MyExtIntHandle ));
                        
                        // Check if subscription is OK
                        if ( MyExtIntHandle >= 0 )
                        {
                            // OK...
                            adl_atSendStdResponsePort ( ADL_AT_RSP, params->Port, ADL_STR_OK );
                        }
                        else
                        {
                            // Reset state
                            signal_Mode = FALSE;
                            
                            // ExtInt Subscription error
                            adl_atSendStdResponseExtPort ( ADL_AT_RSP, params->Port, ADL_STR_CME_ERROR, 3 );
                        }
                    }
                    else
                    {
                        // Reset state
                        signal_Mode = FALSE;
                        
                        // GPIO Subscription error
                        adl_atSendStdResponseExtPort ( ADL_AT_RSP, params->Port, ADL_STR_CME_ERROR, 3 );
                    }
                }
                else
                {
                    // Nothing to do
                    adl_atSendStdResponsePort ( ADL_AT_RSP, params->Port, ADL_STR_OK );
                }
            }
        }
        break;
    }
}



/***************************************************************************/
/*  Function   : adl_main                                                  */
/*-------------------------------------------------------------------------*/
/*  Object     : Customer application initialisation                       */
/*                                                                         */
/*-------------------------------------------------------------------------*/
/*  Variable Name     |IN |OUT|GLB|  Utilisation                           */
/*--------------------+---+---+---+----------------------------------------*/
/*  InitType          |   |   |   |  Application start mode reason         */
/*--------------------+---+---+---+----------------------------------------*/
/***************************************************************************/
void adl_main ( adl_InitType_e InitType )
{
    TRACE (( 1, "Signal Replica Sample: Main" ));
    
    // Interruption & message handlers definition
    MyIrqHandle  = adl_irqSubscribe ( MyIrqHandler, ADL_IRQ_NOTIFY_LOW_LEVEL, ADL_IRQ_PRIORITY_HIGH_LEVEL, ADL_IRQ_OPTION_AUTO_READ );
    TRACE (( 1, "Interruption handler subscription: %d", MyIrqHandle ));
    TRACE (( 1, "Application context diagnostic: %X", adl_ctxGetDiagnostic() ));

    // Get ExtInt Capabilties
    adl_extintGetCapabilities( &irq_ExtIntCapabilities );
        
    // Subscribe to start/stop command if all is OK for IRQ subscription
    if ( MyIrqHandle >= OK )
    {
        // Subscribe to the control command
        adl_atCmdSubscribe ( AtCmdStr_SIGNAL, MyControlCommandHandler, ADL_CMD_TYPE_TEST | ADL_CMD_TYPE_READ | ADL_CMD_TYPE_PARA | 0x51 );

    }
    else if ( MyIrqHandle == ADL_RET_ERR_NOT_SUPPORTED )
    {
        // Feature not enabled
        adl_atSendResponse ( ADL_AT_UNS, "\r\nInit Failed; Real Time enhancement feature not enabled.\r\n" );
    }
    //adl_tmrSubscribe ( FALSE, 100, ADL_TMR_TYPE_100MS, my_function2 );
    adl_tmrSubscribe ( TRUE, 600, ADL_TMR_TYPE_100MS, my_function );

}

and here is the code for the signal generator sample…

/********************************************************************************************/
/*  signal_generator.c   -  Copyright Wavecom S.A. (c) 2006                                 */
/*                                                                                          */
/*                                                                                          */
/* DISCLAIMER OF WARRANTY                                                                   */
/* ======================                                                                   */
/* This Software is provided free of charge on an 'as is' basis. No warranty is given       */
/* by Wavecom S.A. in relation to the Software of the uses to which it may be put by you,   */
/* the user, or its merchantability, fitness or suitability for any particular purpose      */
/* or conditions; and/or that the use of the Software and all documentation relating        */
/* thereto by the Licensee will not infringe any third party copyright or other             */
/* intellectual property rights. Wavecom S.A. shall furthermore be under no obligation      */
/* to provide support of any nature for the Software and the Documentation.                 */
/*                                                                                          */
/* LIMIT OF LIABILITY                                                                       */
/* ==================                                                                       */
/* In no event shall Wavecom S.A. be liable for any loss or damages whatsoever or howsoever */
/* caused arising directly or indirectly in connection with this licence, the Software,     */
/* its use or otherwise except to the extent that such liability may not be lawfully        */
/* excluded. Notwithstanding the generality of the foregoing, Wavecom S.A. expressly        */
/* excludes liability for indirect, special, incidental or consequential loss or damage     */
/* which may arise in respect of the Software or its use, or in respect of other equipment  */
/* or property, or for loss of profit, business, revenue, goodwill or anticipated savings.  */
/*                                                                                          */
/********************************************************************************************/

/***************************************************************************/
/*  File      : signal_generator.c                                         */
/*-------------------------------------------------------------------------*/
/*  Scope     : Signal Generator sample (TCU interrupt handling sample)    */
/*                                                                         */
/***************************************************************************/

#include "adl_global.h"


/***************************************************************************/
/*  Mandatory variables (Call stack sizes)                                 */
/*-------------------------------------------------------------------------*/
/*  wm_apmCustomStackSize                                                  */
/*  wm_apmIRQLowLevelStackSize                                             */
/*  wm_apmIRQHighLevelStackSize                                            */
/*-------------------------------------------------------------------------*/
/***************************************************************************/
const u16 wm_apmCustomStackSize = 1024*3;
const u32 wm_apmIRQLowLevelStackSize =  1024;
const u32 wm_apmIRQHighLevelStackSize = 1024;



/***************************************************************************/
/*  Local variables                                                        */
/***************************************************************************/

// GPIO output to use
#define OUTPUT_GPIO_LABEL ( ADL_IO_GPIO | 0 )

// Time period boundaries, in ms
#define TIME_PERIOD_MIN             3   //in order to work with 300 Hz
#define TIME_PERIOD_MAX             1000
#define TIME_HIGH_LEVEL_PERIOD_MIN  1
#define TIME_HIGH_LEVEL_PERIOD_MAX  ( TIME_PERIOD_MAX - TIME_LOW_LEVEL_MIN )

// Minimum low level duration, in ms
#define TIME_LOW_LEVEL_MIN  1.5         //in order to work with 300 Hz

// Commands strings
static const ascii * AtCmdStr_SIGNAL = "AT+SIGNAL";

// Interrupt handle
static s32 MyIrqHandle;

// TCU service handles
static s32 MyLongTCUHandle = ERROR, MyShortTCUHandle = ERROR;

// GPIO service handle
static s32 MyGpioHandle = ERROR;

// Current signal periods
static u32 signal_Period          = TIME_PERIOD_MIN;
static u32 signal_HighLevelPeriod = TIME_HIGH_LEVEL_PERIOD_MIN;

// Signal generation mode
static bool signal_Mode;

// Signal output GPIO ID
static u8 signal_OutputIo = 0;



/***************************************************************************/
/*  Local functions                                                        */
/***************************************************************************/

/****************************************************************************/
/*  Function   : MyIrqHandler                                               */
/*--------------------------------------------------------------------------*/
/*  Scope  : ADL Interrupt service low level handler                        */
/*                                                                          */
/*  Return :  TRUE to enable High level handler notification                */
/*            FALSE to disable High level handler notification              */
/*                                                                          */
/*--------------------+---+---+---------------------------------------------*/
/*  Variable Name     |IN |OUT|  Use                                        */
/*--------------------+---+---+---------------------------------------------*/
/* Source             | X |   | Interrupt source identifier                 */
/*--------------------+---+---+---------------------------------------------*/
/* NotificationLevel  | X |   | Handler notification level                  */
/*--------------------+---+---+---------------------------------------------*/
/* Data               | X | X | Interrupt event data structure              */
/*--------------------+---+---+---------------------------------------------*/
/****************************************************************************/
static bool MyIrqHandler ( adl_irqID_e Source, adl_irqNotificationLevel_e NotificationLevel, adl_irqEventData_t * Data )
{
    s32 sReturn;
    adl_ioDefs_t Gpio_to_write = ADL_IO_GPIO | signal_OutputIo ;
    
    // WARNING: low level execution context
    TRACE (( 2, "TCU interrupt handler (Context: %.2X)", Data->Context ));
    
    // Check context provided at subscription time
    // 0 --> short timer
    // 1 --> long timer
    if ( !Data->Context )
    {
        // Short Timer Interrupt: set output to 0
        sReturn = adl_ioWriteSingle ( MyGpioHandle, &Gpio_to_write , FALSE );
    }
    else
    {
        // Long Timer Interrupt: set output to 1...
        sReturn = adl_ioWriteSingle ( MyGpioHandle, &Gpio_to_write, TRUE );
        
        // ... and start short timer
        adl_tcuStart ( MyShortTCUHandle );
    }
    
    // Trace only IO write errors
    if ( sReturn < 0 )
    {
        TRACE (( 2, "adl_ioWriteSingle GPIO %d : %d error %X ", signal_OutputIo, sReturn , Gpio_to_write & ADL_IO_ERR_MSK ));
    }
    
    return FALSE;
}



/****************************************************************************/
/*  Function   : MyControlCommandHandler                                    */
/*--------------------------------------------------------------------------*/
/*  Scope  : AT+SIGNAL command handler                                      */
/*                                                                          */
/*  Return : VOID                                                           */
/*                                                                          */
/*--------------------+---+---+---------------------------------------------*/
/*  Variable Name     |IN |OUT|  Use                                        */
/*--------------------+---+---+---------------------------------------------*/
/* params             | X |   | Incoming AT command parameters              */
/*--------------------+---+---+---------------------------------------------*/
/****************************************************************************/
static void MyControlCommandHandler ( adl_atCmdPreParser_t * params )
{
    ascii RspStr [ 80 ];

    // Switch on command type
    switch ( params->Type )
    {
        // Test command
        case ADL_CMD_TYPE_TEST :
            wm_sprintf ( RspStr, "\r\n%s: (0-1),(0-%d),(%d-%d),(%d-%d)\r\n", AtCmdStr_SIGNAL + 2, ADL_IO_NUM_MSK, TIME_PERIOD_MIN, TIME_PERIOD_MAX, TIME_HIGH_LEVEL_PERIOD_MIN, TIME_HIGH_LEVEL_PERIOD_MAX );
            adl_atSendResponsePort ( ADL_AT_RSP, params->Port, RspStr );
            adl_atSendStdResponsePort ( ADL_AT_RSP, params->Port, ADL_STR_OK );
        break;
        
        // Read command
        case ADL_CMD_TYPE_READ :
            wm_sprintf ( RspStr, "\r\n%s: %d,%d,%d,%d\r\n", AtCmdStr_SIGNAL + 2, signal_Mode, signal_OutputIo, signal_Period, signal_HighLevelPeriod );
            adl_atSendResponsePort ( ADL_AT_RSP, params->Port, RspStr );
            adl_atSendStdResponsePort ( ADL_AT_RSP, params->Port, ADL_STR_OK );
        break;
        
        // Parameters command
        case ADL_CMD_TYPE_PARA :
        {
            // Analyses parameters
            ascii * P0 = ADL_GET_PARAM ( params, 0 ),
                  * P1 = ADL_GET_PARAM ( params, 1 ),
                  * P2 = ADL_GET_PARAM ( params, 2 ),
                  * P3 = ADL_GET_PARAM ( params, 3 );
            u16 iP0, iP1 = signal_OutputIo;
            u32 iP2, iP3;
            s32 sReturn;
            
            // Check Parameters
            if ( !P0
              // Mode
              || ( ( iP0 = wm_atoi ( P0 ) ) > 1 )
              // Output IO ID
              || ( P1
                && ( ( ( iP1 = wm_atoi ( P1 ) ) < 1 )
                  || ( iP1 > ADL_IO_NUM_MSK )
                   )
                 )
              // Time period
              || ( P2
                && ( ( ( iP2 = wm_atoi ( P2 ) ) < TIME_PERIOD_MIN )
                  || ( iP2 > TIME_PERIOD_MAX )
                  || ( !P3 && ( iP2 < iP3 + TIME_LOW_LEVEL_MIN ) )
                   )
                 )
              // High level Time period
              || ( P3
                && ( ( ( iP3 = wm_atoi ( P3 ) ) < TIME_HIGH_LEVEL_PERIOD_MIN )
                  || ( iP3 > TIME_HIGH_LEVEL_PERIOD_MAX )
                  || ( !P2 && ( iP3 > signal_HighLevelPeriod - TIME_LOW_LEVEL_MIN ) )
                  || ( P2 && ( iP3 > iP2 - TIME_LOW_LEVEL_MIN ) )
                   )
                 )
               )
            {
                // Syntax error
                adl_atSendStdResponseExtPort ( ADL_AT_RSP, params->Port, ADL_STR_CME_ERROR, 3 );
            }
            else
            {
                // Check if signal is running
                if ( signal_Mode )
                {
                    // Unsubscribe from TCU services
                    sReturn = adl_tcuUnsubscribe ( MyLongTCUHandle );
                    MyLongTCUHandle = ERROR;
                    TRACE (( 1, "Unsubscribe from TCU long timer: %d", sReturn ));
                    sReturn = adl_tcuUnsubscribe ( MyShortTCUHandle );
                    MyShortTCUHandle = ERROR;
                    TRACE (( 1, "Unsubscribe from TCU short timer: %d", sReturn ));
                    
                    // Unsubscribe from GPIO
                    sReturn = adl_ioUnsubscribe ( MyGpioHandle );
                    MyGpioHandle = ERROR;
                    TRACE (( 1, "Unsubscribe from GPIO %d: %d", signal_OutputIo, sReturn ));
                }
                
                // Update signal mode
                signal_Mode = iP0;
                TRACE (( 1, "New signal mode: %d", signal_Mode ));
                
                // Check for mode
                if ( signal_Mode )
                {
                    adl_tcuTimerSettings_t TCUSettings = { { 0, ADL_TCU_TIMER_UNIT_MS }, TRUE };
                    
                    // GPIO 0 by default
                    adl_ioDefs_t GpioConfig = OUTPUT_GPIO_LABEL | ADL_IO_DIR_OUT | ADL_IO_LEV_LOW ;
                    
                    // Set time periods (if supplied)
                    if ( P2 )
                    {
                        signal_Period = iP2;
                    }
                    if ( P3 )
                    {
                        signal_HighLevelPeriod = iP3;
                    }
                    
                    // Fill IO settings, according to desired value (if supplied)
                    GpioConfig = GpioConfig | iP1 ;
                    TRACE (( 1, "GPIO ID for current product: %d", iP1 ));
                    
                    // Subscribe IO
                    MyGpioHandle = adl_ioSubscribe ( 1, &GpioConfig, 0, 0, 0 );
                    TRACE (( 1, "Subscribe to GPIO %X: %d error code %X", GpioConfig & ADL_IO_LABEL_MSK,MyGpioHandle, GpioConfig & ADL_IO_ERR_MSK ));
                    
                    // Check if subscription is OK
                    if ( MyGpioHandle >= 0 )
                    {
                        // Remember GPIO id
                        signal_OutputIo = iP1;
                        
                        // Fill TCU settings, according to time period (in ms)
                        TCUSettings.Duration.DurationValue = signal_Period;
                        TRACE (( 1, "TCU configured for a %d ms long timer", signal_Period ));
                        
                        // Subscribe to the TCU service
                        MyLongTCUHandle = adl_tcuSubscribe ( ADL_TCU_ACCURATE_TIMER, 0, MyIrqHandle, &TCUSettings, (void*) 1 );
                        TRACE (( 1, "Subscribe to long TCU timer: %d", MyLongTCUHandle ));
                        
                        // Fill TCU settings, according to time period (in ms)
                        TCUSettings.Duration.DurationValue = signal_HighLevelPeriod;
                        TCUSettings.Periodic = FALSE;   // One shot timer
                        TRACE (( 1, "TCU configured for a %d ms short timer", signal_HighLevelPeriod ));
                        
                        // Set the second timer
                        MyShortTCUHandle = adl_tcuSubscribe ( ADL_TCU_ACCURATE_TIMER, 0, MyIrqHandle, &TCUSettings, (void*) 0 );
                        TRACE (( 1, "Subscribe to short TCU timer: %d", MyShortTCUHandle ));
                        
                        // Check if subscription are OK
                        if ( ( MyLongTCUHandle >= 0 )
                          && ( MyShortTCUHandle >= 0 ) )
                        {
                            // Start the timer...
                            sReturn = adl_tcuStart ( MyLongTCUHandle );
                            TRACE (( 1, "Start TCU: %d", sReturn ));
                            
                            // OK...
                            adl_atSendStdResponsePort ( ADL_AT_RSP, params->Port, ADL_STR_OK );
                        }
                        else
                        {
                            // Reset state
                            signal_Mode = FALSE;
                            
                            // TCU Subscription error
                            adl_atSendStdResponseExtPort ( ADL_AT_RSP, params->Port, ADL_STR_CME_ERROR, 3 );
                        }
                    }
                    else
                    {
                        // Reset state
                        signal_Mode = FALSE;
                        
                        // GPIO Subscription error
                        adl_atSendStdResponseExtPort ( ADL_AT_RSP, params->Port, ADL_STR_CME_ERROR, 3 );
                    }
                }
                else
                {
                    // Nothing to do
                    adl_atSendStdResponsePort ( ADL_AT_RSP, params->Port, ADL_STR_OK );
                }
            }
        }
        break;
    }
}



/****************************************************************************/
/*  Function   : adl_main                                                   */
/*--------------------------------------------------------------------------*/
/*  Scope      : Customer application initialisation                        */
/*                                                                          */
/*--------------------+---+---+---------------------------------------------*/
/*  Variable Name     |IN |OUT|  Use                                        */
/*--------------------+---+---+---------------------------------------------*/
/* InitType           | X |   | Application start mode reason               */
/*--------------------+---+---+---------------------------------------------*/
/****************************************************************************/
void adl_main ( adl_InitType_e InitType )
{
    TRACE (( 1, "Signal Generator sample: Main" ));
    
    // Interrupt handler definition
    MyIrqHandle  = adl_irqSubscribe ( MyIrqHandler,  ADL_IRQ_NOTIFY_HIGH_LEVEL,  ADL_IRQ_PRIORITY_HIGH_LEVEL, ADL_IRQ_OPTION_AUTO_READ | ADL_IRQ_OPTION_POST_ACKNOWLEDGEMENT );
    TRACE (( 1, "Interrupt handler subscription: %d", MyIrqHandle ));
    TRACE (( 1, "Application context diagnostic: %X", adl_ctxGetDiagnostic() ));
        
    // Subscribe to start/stop command if all is OK for IRQ subscription
    if ( MyIrqHandle >= OK )
    {
        // Subscribe to the control command
        adl_atCmdSubscribe ( (ascii*) AtCmdStr_SIGNAL, MyControlCommandHandler, ADL_CMD_TYPE_TEST | ADL_CMD_TYPE_READ | ADL_CMD_TYPE_PARA | 0x41 );
    }
}