[Tinyos-contrib-commits] CVS: tinyos-1.x/contrib/handhelds/tos/lib/RovingNetworks RovingNetworksM.nc, NONE, 1.1

steve ayer ayer1 at users.sourceforge.net
Fri Mar 9 12:17:40 PST 2007


Update of /cvsroot/tinyos/tinyos-1.x/contrib/handhelds/tos/lib/RovingNetworks
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv20622/RovingNetworks

Added Files:
	RovingNetworksM.nc 
Log Message:

new library module implementing (also new) Bluetooth interface on
rovingnetworks mitsumi rn46-based bluetooth device


--- NEW FILE: RovingNetworksM.nc ---
/*
 * Copyright (c) 2007, Intel Corporation
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * Redistributions of source code must retain the above copyright notice, 
 * this list of conditions and the following disclaimer. 
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution. 
 *
 * Neither the name of the Intel Corporation nor the names of its contributors
 * may be used to endorse or promote products derived from this software 
 * without specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 * POSSIBILITY OF SUCH DAMAGE.
 *
 *  Author:  Steve Ayer
 *           February, 2007
 */

includes msp430baudrates;
includes RovingNetworks;

module RovingNetworksM {
  provides {
    interface StdControl;
    interface Bluetooth;
  }
  uses {
    interface StdControl as TimerControl;
    interface Timer as OverflowTimer;
    interface HPLUSARTControl as UARTControl;
    interface HPLUSARTFeedback as UARTData;
    interface MSP430Interrupt as RTSInterrupt;
    interface MSP430Interrupt as ConnectionInterrupt;
    interface MessagePool;
    interface Leds;
  }
}

implementation {

  extern int sprintf(char *str, const char *format, ...) __attribute__ ((C));
  extern int snprintf(char *str, size_t len, const char *format, ...) __attribute__ ((C));

  uint8_t radioMode, charsSent, setupStep;
  bool discoverable, authenticate, encrypt, setNameRequest, setPINRequest, runDiscoveryRequest, resetDefaultsRequest;
  norace bool transmissionOverflow, messageInProgress;
  char expectedCommandResponse[8], newName[17], newPIN[17];
  
  norace struct Message * outgoingMsg;
  norace struct Message * incomingMsg;

  void sendNextChar() {
    if(charsSent < msg_get_length(outgoingMsg)) {
      call UARTControl.tx(msg_get_uint8(outgoingMsg, charsSent));
      charsSent++;
    } 
    else{
      messageInProgress = FALSE;
      if(!*expectedCommandResponse)
	signal Bluetooth.writeDone();
    }	    
  }
  
  command result_t Bluetooth.write(const uint8_t * buf, uint16_t len) { 
    if(messageInProgress)
      return FAIL;

    messageInProgress = TRUE;
    charsSent = 0;
    msg_clear(outgoingMsg);
    msg_append_buf(outgoingMsg, buf, len);

    if(!transmissionOverflow){
      sendNextChar();
    }
	
    return SUCCESS;
  }
    
  void initRN() {
    register uint16_t i;
    /*
     * powerup state is reset == low (true); mike conrad of roving networks sez: 
     * wait about 1/2 s after reset toggle
     */
    TOSH_SET_BT_RESET_PIN();    
    for(i = 0; i < 100 ; i++)   // == 500k us
      TOSH_uwait(5000);

    TOSH_MAKE_BT_PIO_INPUT();   // this is the connection interrupt pin, was default output
    
    call RTSInterrupt.edge(TRUE);  // initially, we look for a connection
    call RTSInterrupt.enable();  // request to send raises when bt has trans overflow
    call RTSInterrupt.clear();
    
    call ConnectionInterrupt.edge(TRUE);  // initially, we look for a connection
    call ConnectionInterrupt.enable();  // interrupt upon connection state change (raises when connected, falls when dropped)
    call ConnectionInterrupt.clear();

    TOSH_CLR_BT_CTS_PIN();     // toggling cts wakes it up
    TOSH_SET_BT_CTS_PIN();     
    TOSH_uwait(5000);
    TOSH_CLR_BT_CTS_PIN();     // tell bt module msp430 is ready
  }

  void setupUART() {
    call UARTControl.setClockSource(SSEL_SMCLK);
    call UARTControl.setClockRate(UBR_SMCLK_115200, UMCTL_SMCLK_115200);
    call UARTControl.setModeUART();
    call UARTControl.enableTxIntr();
    call UARTControl.enableRxIntr();
  }

  /*
   * poll?  what's going on here?  mike conrad asserts that the module fw 
   * should be able to respond to a command request within about 50ms,
   * so instead of posting a separate task for each command (messy!),
   * we'll just poll inline and wait for the uart to tell us it has 
   * heard back from the bt module by setting the expectedResponse to NULL
   */
  result_t poll_for_fifty_msec() {
    register uint8_t i;
    
    for(i = 0; i < 100; i++)
      TOSH_uwait(5000);

    if(*expectedCommandResponse)     
      return FAIL;
    else
      return SUCCESS;
  }

  void disableRN() {
    TOSH_CLR_BT_RESET_PIN();
    call UARTControl.disableUART();
    call RTSInterrupt.disable();  
    call ConnectionInterrupt.disable();  
  }

  result_t writeCommand(char * cmd, char * response) {
    strcpy(expectedCommandResponse, response);
    if(call Bluetooth.write(cmd, strlen(cmd)) == FAIL)
      return FAIL;

    return SUCCESS;
  }

  command void Bluetooth.setRadioMode(uint8_t mode){
    radioMode = mode;
  }    

  command void Bluetooth.setDiscoverable(bool disc){
    discoverable = disc;  
  }    

  command void Bluetooth.setEncryption(bool enc){
    encrypt = enc; 
  }    

  command void Bluetooth.setAuthentication(bool auth){
    authenticate = auth;
  }    

  command void Bluetooth.resetDefaults(){
    resetDefaultsRequest = TRUE;
  }    

  command void Bluetooth.setName(char * name){
    setNameRequest = TRUE;
    snprintf(newName, 17, "%s", name);
  }    

  command void Bluetooth.setPIN(char * PIN){
    setPINRequest = TRUE;
    snprintf(newPIN, 17, "%s", PIN);
  }    

  /*
   * this one is weird.  we need to do one at a time; the only way
   * to get back is if the previous command responds properly and calls
   * back to runSetCommands().  so if we get into command mode, each time here 
   * we have to send another command.  we keep falling down the switch 
   * until we find it, eventually hitting end.
   */
  task void runSetCommands() {
    char commandbuf[32];

    // if we're in default mode, don't even go to cmd mode
    /*
    if(!radioMode &&     
       discoverable &&
       !authenticate &&
       !setNameRequest &&
       !setPINRequest &&
       !encrypt){
      signal Bluetooth.commandModeEnded();
      return;
    }
    */
    switch(setupStep) {
    case 0:
      setupStep++;
      writeCommand("$$$", "CMD");
      break;
    case 1:
      setupStep++;
      // reset factory defaults
      writeCommand("SF,1\r", "AOK");
      break;
    case 2:
      setupStep++;
      // default is slave (== 0), otherwise set mode
      if(radioMode){
	sprintf(commandbuf, "SM,%d\r", radioMode);
	writeCommand(commandbuf, "AOK");
	break;
      }
    case 3:
      setupStep++;
      /*
       * device is discoverable with a non-zero inquiry scan window
       * default "time" is 0x0200 (units unspecified)
       */
      if(!discoverable){
	writeCommand("SI,0x0000\r", "AOK");
	break;
      }
    case 4:
      setupStep++;
      // device default is off
      if(authenticate){
	writeCommand("SA,1\r", "AOK");
	break;
      }
    case 5:
      setupStep++;
      // device default is off
      if(encrypt){
	writeCommand("SE,1\r", "AOK");
	break;
      }
    case 6:
      setupStep++;
      // default is none
      if(setNameRequest){
	sprintf(commandbuf, "SN,%s\r", newName);
	writeCommand(commandbuf, "AOK");
	break;
      }
    case 7:
      setupStep++;
      // default is none
      if(setPINRequest){
	sprintf(commandbuf, "SP,%s\r", newPIN);
	writeCommand(commandbuf, "AOK");
	break;
      }
    case 8:
      setupStep++;
      // exit command mode
      writeCommand("---\r", "END");
      break;
    default:
      break;
    }
  }

  command result_t StdControl.init(){
    radioMode = SLAVE_MODE;   
    discoverable = TRUE;
    authenticate = FALSE;
    encrypt = FALSE;
    resetDefaultsRequest = FALSE;
    setNameRequest = FALSE;
    setPINRequest = FALSE;

    setupStep = 0;
    *expectedCommandResponse = NULL;
    transmissionOverflow = FALSE, messageInProgress = FALSE;

    call TimerControl.init();
    call MessagePool.init();
    
    outgoingMsg = call MessagePool.alloc();
    incomingMsg = call MessagePool.alloc();

    //    call Leds.init();

    initRN();
    setupUART();

    return SUCCESS;
  }

  command result_t StdControl.start(){
    call TimerControl.start();

    post runSetCommands();

    return SUCCESS;
  }

  command result_t StdControl.stop(){
    call TimerControl.stop();

    disableRN();

    call MessagePool.free(incomingMsg);
    call MessagePool.free(outgoingMsg);

    return SUCCESS;
  }

  /* this will turn off the Bluetooth module */
  /* 
   * sma sez:  yeah but, do we really need this?  
   * can't we just call stdcontrol.stop in an app? 
   */
  command result_t Bluetooth.disable(){ 
    call StdControl.stop();

    return SUCCESS;
  }

 /* after this command is called there will be no link to the connected device */
  command result_t Bluetooth.disconnect(){
    call Bluetooth.write("K,\r", 3);
  }

  /* commands useful for Master(client) applications only */
  /* do an BT Inquiry to discover all listening devices within range */
  command void Bluetooth.discoverDevices() {
    if(!radioMode)     // we're a slave, shouldn't do this
      return;

    runDiscoveryRequest = TRUE;
  }    

  /* connect to a specific device that was previously discovered */
  command result_t Bluetooth.connect(uint8_t * addr) {
    char buffer[64];

    sprintf(buffer, "C,%s\r", addr);
    return writeCommand(buffer, "AOK");
  }
     
  async event result_t UARTData.rxDone(uint8_t data) {        
    if(!*expectedCommandResponse)
      signal Bluetooth.dataAvailable(data);
    else{
      if(isalpha(data)){
	msg_append_uint8(incomingMsg, data);
	if(msg_cmp_buf(incomingMsg,            // which is affirmative
		       0, 
		       expectedCommandResponse,
		       strlen(expectedCommandResponse))){
	  msg_clear(incomingMsg);	
	  if(!strcmp(expectedCommandResponse, "END"))
	    signal Bluetooth.commandModeEnded();//call Leds.greenOn();
	  else
	    post runSetCommands();
	  *expectedCommandResponse = '\0';
	}
      }
      else
	msg_clear(incomingMsg);
    }
    return SUCCESS;
  }

  async event result_t UARTData.txDone() {
    if (!transmissionOverflow) {
      sendNextChar();
    }
    return SUCCESS;
  }
    
  event result_t OverflowTimer.fired() {
    if (call RTSInterrupt.getValue() == FALSE) {
      transmissionOverflow = 0;
      sendNextChar();
      //      call Leds.redOff();
    } 
    else
      call OverflowTimer.start(TIMER_ONE_SHOT, 10);	    

    return SUCCESS;
  }

  // Interrupt associated with radio flow control.  Ensures that there are no buffer overflows.
  async event void RTSInterrupt.fired() {
    if (call RTSInterrupt.getValue() == TRUE) {
      transmissionOverflow = 1;
      call OverflowTimer.start(TIMER_ONE_SHOT, 10);
      //      call Leds.redOn();
    } 
    atomic call RTSInterrupt.clear();
  }
  
  async event void ConnectionInterrupt.fired() {
    if(call ConnectionInterrupt.getValue() == TRUE){
      call ConnectionInterrupt.edge(FALSE);
      signal Bluetooth.connectionMade(SUCCESS);
    }
    else{

      call ConnectionInterrupt.edge(TRUE);
      signal Bluetooth.connectionClosed(0);
    }
    call ConnectionInterrupt.clear();
  }
  
}



More information about the Tinyos-contrib-commits mailing list