Using SleepModule and PassThrough at the same time?

Searched a bit, found one thread on low power operation, but my situation is a bit different. I have a number of XBee Pro S2B programmable modules and am using them as “straight” S2B modules by just hard coding the choice to enter passthrough mode in the bootloader.

Yes, it seems a bit foolish on the surface, but the idea was that the programmable version gave growth beyond the current app which works just fine using std API commands

Then I measured the power draw on a module that was supposed to be drawing micro watts because we were in pin-sleep. And found that the unit was drawing ~14-15 mAmps — a number that looks suspiciously like the freescale processor power draw mentioned in the manual (pg 10 of the 90000976_F version of the users guide).

Digging into the sample app, the SleepModule() method would obviously be the answer – if I had written a main loop to run in the code. Sample app is OK - but it assumes someone typing on the host and my app has another microprocessor acting as the “host” to the zigbee module. Not really interested in trying to hack the assemby code that implements the pass through mode in the bootloader app.

Anyone have any suggestions (beyond the obvious one of suck it up and write my own pass through code for the freescale processor. ??).

Alternative is to just buy the regular S2B modules - but would be nice if could still work with the programmable modules.

thanks !

Not A Team Player …

Your code must do more than simply enter bypass mode.
It must monitor the sleep line IO_DIO9_ADC9_ON_SLEEP at the same time.
You should copy the bypass mode of the bootloader to your App code. (It doesn’t pass the reset line.)
Delete the line " DisableInterrupts;"

At startup you need to check the reset cause.
if (SRS_PIN) { then reset the EM250 for 1mS }

Don’t init() the UARTS, Only Enable the interrupt for Sleep line monitoring. and then run the local passthrough Code without disabling interrupts.

I am required according to the sample code to include this in my redistribution of the modified version of Digi Code.

Copyright (C) 20140 Digi International, All Rights Reserved.
*
*

  • This software is provided as instructional material without charge
  • by Digi International for use by its employees and customers
  • subject to the following terms.
  • PERMISSION
  • Permission is hereby granted, free of charge, to any person obtaining
  • a copy of this software, to deal with it without restriction,
  • including without limitation the rights to use, copy, modify, merge, publish,
  • distribute, sublicense, and/or sell copies of it, and to permit persons to
  • whom it is furnished to do so, provided the above copyright notice
  • and this permission notice are included in all derived works
  • and the use of this software is restricted to Digi products.
  • WARRANTY
  • THIS SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
  • OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  • FITNESS FOR A PARTICULAR PURPOSE, OR NONINFRINGEMENT.
  • LIABILITY
  • IN NO EVENT SHALL DIGI INTERNATIONAL BE LIABLE FOR ANY CLAIM, DAMAGES,
  • OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE,
  • ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE, OR THE USE
  • OR OTHER DEALINGS WITH THE SOFTWARE.

Now that that is done, here is the code
void InitKeyboardInterrupt(void)
{
#define IO_DIO9_ADC9_ON_SLEEP_INTERUPT2 KBI2PE_KBIPE5_MASK
#define IO_DIO9_ADC9_ON_SLEEP_RISING_EDGE() KBI2ES_KBEDG5=1
#define IO_DIO9_ADC9_ON_SLEEP_FALLING_EDGE() KBI2ES_KBEDG5=0
#define IO_DIO9_ADC9_ON_SLEEP_TOGGLE_EDGE() KBI2ES_KBEDG5=!KBI2ES_KBEDG5
//KB_INTERUPT2_DETECT_EDGE();
KB_INTERUPT2_DETECT_EDGE_AND_LEVEL()
//IO_DIO5_ASSOCIATE_RISING_EDGE();
IO_DIO9_ADC9_ON_SLEEP_FALLING_EDGE()

KB_INTERUPT2_DISABLE(0xFF);//disable all
KB_INTERUPT1_DISABLE();//disable all
//KB_INTERUPT2_ENABLE(IO_DIO5_ASSOCIATE_INTERUPT2);
KB_INTERUPT2_ENABLE( IO_DIO9_ADC9_ON_SLEEP_INTERUPT2);

//associateTicksL = -1;//next tick will clear to 0;
//radioType = RADIO_TYPE_UNKNOWN;
}

Now rewrite the Code for the Associate Interrupt to take care of sleeping the module.
The interrupt occurs.
Clear the interrupt flag
Read the Sleep line.
Set the Interrupt to detect the opposite level. (AKA. high Set for Falling edge)
if EM250 is Sleeping enable interrupts and then go to sleep and and then return.
if EM250 is not Sleeping just return.

You will call the interrupt, sleep the module, call the interrupt again to wake up, then return twice.

This doesn’t support OTA updates.
The Application must have a way of returning to the bootloader in order to support OTA updates.

Great - thanks so much for the quick reply. I’ll give that a try.

NATP

Here is a good starting point, for someone who needs the same sort of thing.
I finished trying this pass through that can sleep.

Over the air updates are not possible. at this point.
But could easily be added under another ISR.
Then using Over The Air Commands from Zigbee, an IO line could be changed. And then that ISR could call back into the Bootloader for an update.

And one added thing. you must set the keyboard interrupt vector to the new Interrupt routine. (ISR)
The rest of the code is in the previous post.

#define IO_DIO5_ASSOCIATE_INTERRUPT2 KBI2PE_KBIPE4_MASK
#define IO_DIO5_ASSOCIATE_RISING_EDGE() KBI2ES_KBEDG4=1
#define IO_DIO5_ASSOCIATE_FALLING_EDGE() KBI2ES_KBEDG4=0
#define IO_DIO5_ASSOCIATE_TOGGLE_EDGE() KBI2ES_KBEDG4=!KBI2ES_KBEDG4

#define IO_DIO9_ADC9_ON_SLEEP_INTERRUPT2 KBI1PE_KBIPE1_MASK
#define IO_DIO9_ADC9_ON_SLEEP_RISING_EDGE() KBI1ES_KBEDG1=1
#define IO_DIO9_ADC9_ON_SLEEP_FALLING_EDGE() KBI1ES_KBEDG1=0
#define IO_DIO9_ADC9_ON_SLEEP_TOGGLE_EDGE() KBI1ES_KBEDG1=!KBI1ES_KBEDG1

#define KB_INTERRUPT2_FLAG() KBI2SC_KBF
#define KB_INTERRUPT2_CLEAR() KBI2SC_KBACK=1
#define KB_INTERRUPT2_DETECT_EDGE_AND_LEVEL() KBI2SC_KBIMOD=1
#define KB_INTERRUPT2_DETECT_EDGE() KBI2SC_KBIMOD=0
#define KB_INTERRUPT2_ENABLE(pins) KBI2PE |= pins;
KBI2SC_KBIE=1
#define KB_INTERRUPT2_DISABLE_ALL() KBI2PE=0;
KBI2SC_KBIE=0
#define KB_INTERRUPT2_DISABLE(pins) KBI2PE &= ~pins;
if(!KBI2PE)
{
KBI2SC_KBIE=0;
}

#define KB_INTERRUPT1_FLAG() KBI1SC_KBF
#define KB_INTERRUPT1_CLEAR() KBI1SC_KBACK=1
#define KB_INTERRUPT1_DISABLE() KBI1SC_KBIE=0
#define KB_INTERRUPT1_DETECT_EDGE_AND_LEVEL() KBI1SC_KBIMOD=1
#define KB_INTERRUPT1_DETECT_EDGE() KBI1SC_KBIMOD=0
#define KB_INTERRUPT1_ENABLE_PINS(pins) KBI1PE |= pins;
KBI1SC_KBIE=1
#define KB_INTERRUPT1_ENABLE() KBI1SC_KBIE=1

#define STOP_MODE() __asm STOP;
#define WAIT_MODE() __asm WAIT;

void initGPIO(void)
{
PTADD = 0;//set all as inputs
PTBDD = 0;//set all as inputs
PTCDD = 0;//set all as inputs
PTDDD = 0;//set all as inputs
PTEPE = 0x70;//turn on Hardware detect pull-ups
PTEDD = 0;//set all as inputs
portE = PTED & HARDWARE_MASK_PORTE;//read hardware detect lines

PTAPE = 1<<6 | 1<<5 | 1<<4;//disable pullups except for no connects
PTBPE = 0xC1;//3<<6+1;//disable pullups except for no connects and DIN
PTCPE = 1<<6 | 7<<2;//disable pullups except for no connects and RESET_XBEE
PTDPE = 0xF;//disable pullups except for no connects
PTEPE = portE | 0x8F;//disable pullups except for no connects

IO_DIO7_CTS_HOST = 1; //De-Assert CTS Line
IO_DIO7_CTS_HOST_D = 1; //Set CTS as output to computer
IO_DIO7_CTS_HOST_PE = 0;
}

void enableSleepDetectionInterrupt(void)
{

KB_INTERRUPT1_DISABLE();//disable all
KB_INTERRUPT1_ENABLE_PINS(IO_DIO9_ADC9_ON_SLEEP_INTERRUPT2);//
KB_INTERRUPT1_DETECT_EDGE_AND_LEVEL();
IO_DIO9_ADC9_ON_SLEEP_RISING_EDGE();//wait for the EMBER to turn on after a reset
KB_INTERRUPT1_ENABLE();
EnableInterrupts;

}

#pragma TRAP_PROC
void SleepModuleISR(void){//keyboard ISR
if (KB_INTERRUPT2_FLAG()){
KB_INTERRUPT2_DISABLE_ALL();//this one should be disabled
KB_INTERRUPT2_CLEAR();
}
if (KB_INTERRUPT1_FLAG()){
if (IO_DIO9_ADC9_ON_SLEEP){//Is the EMBER ON? set interrupt for when it transitions to low

    IO_DIO9_ADC9_ON_SLEEP_FALLING_EDGE(); //this code should only execute once
    KB_INTERRUPT1_CLEAR();
  }else{
    IO_DIO7_CTS_HOST = 1;   //De-Assert CTS Line
    IO_DIO9_ADC9_ON_SLEEP_RISING_EDGE();  
    KB_INTERRUPT1_CLEAR();
    SPMSC1 = 0;//turn off low voltage detection for lower sleep current
    //KB_INTERRUPT1_ENABLE(); //WARNING!!!  never enable interrupt before sleeping. ISR might happen between this line and the next.
    STOP_MODE(); //Module will wake after Interrupt happens even though interrupts are not enabled.
    SPMSC1 = 1;//turn on low voltage detection
    IO_DIO9_ADC9_ON_SLEEP_FALLING_EDGE();//module is now awake
    KB_INTERRUPT1_CLEAR();
  }
}

}