⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rovingnetworksp.nc

📁 tinyos-2.x.rar
💻 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
 */
/**
 * @author Steve Ayer
 * @author Adrian Burns
 * @date February, 2007
 *
 * @author Mike Healy
 * @date April 20, 2009 - ported to TinyOS 2.x 
 */


#include "RovingNetworks.h"
#include "Message.h"

module RovingNetworksP {
  provides {
    interface Init;
    interface StdControl;
    interface Bluetooth;
  }
  uses {
    interface HplMsp430Usart as UARTControl;
    interface HplMsp430UsartInterrupts as UARTData;
    interface HplMsp430Interrupt as RTSInterrupt;
    interface HplMsp430Interrupt as ConnectionInterrupt;
    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,
    setSvcClassRequest, setDevClassRequest, setSvcNameRequest, setCustomBaudrate, disableRemoteConfig, newMode,
    setCustomInquiryTime, setCustomPagingTime;
  norace bool transmissionOverflow, messageInProgress;
  char expectedCommandResponse[8], newName[17], newPIN[17], newSvcClass[5], newDevClass[5], newSvcName[17], newBaudrate[5],
    newInquiryTime[5], newPagingTime[5];
  
  norace struct Message outgoingMsg;
  norace struct Message incomingMsg;
   

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

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

    if(!transmissionOverflow){
      post 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< 400; i++)
      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.clear();
    call ConnectionInterrupt.enable();  // interrupt upon connection state change (raises when connected, falls when dropped)

    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() {
    msp430_uart_union_config_t RN_uart_config = { {ubr: UBR_1MHZ_115200, umctl: UMCTL_1MHZ_115200, 
						   ssel: 0x02, pena: 0, pev: 0, spb: 0, clen: 1,listen: 0, mm: 0, ckpl: 0, urxse: 0, urxeie: 0, 
						   urxwie: 0, utxe : 1, urxe :1} };

#ifdef USE_8MHZ_CRYSTAL           // we need exact divisors, else the thing acts unpredictably
    call UARTControl.setUbr(0x08);
    call UARTControl.setUmctl(0xee);
#endif
    call UARTControl.setModeUart(&RN_uart_config); // set to UART mode

    call UARTControl.enableTxIntr();
    call UARTControl.enableRxIntr();
  }

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

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

    return SUCCESS;
  }

  command void Bluetooth.setRadioMode(uint8_t mode){
    newMode = TRUE;
    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.disableRemoteConfig(bool disableConfig){
    disableRemoteConfig = disableConfig;
  }    

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

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

  command void Bluetooth.setDeviceClass(char * class){
    setDevClassRequest = TRUE;
    snprintf(newDevClass, 5, "%s", class);
  }    

  command void Bluetooth.setServiceClass(char * class){
    setSvcClassRequest = TRUE;
    snprintf(newSvcClass, 5, "%s", class);
  }    

  command void Bluetooth.setServiceName(char * name){
    setSvcNameRequest = TRUE;
    snprintf(newSvcName, 5, "%s", name);
  }    

  /* 
   * this one makes sense only to roving networks
   * the supplied "rate_factor" is the baudrate * 0.004096
   * this factor must be an integer value...
   */
  command void Bluetooth.setBaudrate(char * rate_factor){
    setCustomBaudrate = TRUE;
    snprintf(newBaudrate, 5, "%s", rate_factor);
  }    

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

  /* 
   * Sets the Inquiry Scan Window - amount of time device 
   * spends enabling inquiry scan (discoverability).
   * Minimum = (hex word) "0012", corresponding to about 1% duty cycle.
   * Maximum = (hex word) "1000"
   */
  command void Bluetooth.setInquiryTime(char * hexval_time){
    setCustomInquiryTime = TRUE;
    snprintf(newInquiryTime, 5, "%s", hexval_time);
  }    

  /* 
   * Sets the Paging Scan Window - amount of time device 
   * spends enabling page scan (connectability).
   * Minimum = (hex word) "0012", corresponding to about 1% duty cycle.
   * Maximum = (hex word) "1000"
   */
  command void Bluetooth.setPagingTime(char * hexval_time){
    setCustomPagingTime = TRUE;
    snprintf(newPagingTime, 5, "%s", hexval_time);
  }    

  /*
   * 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];

    switch(setupStep) {
    case 0:
      setupStep++;
      writeCommand("$$$", "CMD");
      break;
    case 1:
      setupStep++;
      // reset factory defaults
      if(resetDefaultsRequest){
	writeCommand("SF,1\r", "AOK");
	break;
      }
    case 2:
      setupStep++;
      // default is slave (== 0), otherwise set mode
      if(newMode){
	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,0000\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++;
      if(setSvcClassRequest){
	sprintf(commandbuf, "SC,%s\r", newSvcClass);
	writeCommand(commandbuf, "AOK");
	break;
      }
    case 9:
      setupStep++;
      if(setDevClassRequest){
	sprintf(commandbuf, "SD,%s\r", newDevClass);
	writeCommand(commandbuf, "AOK");
	break;
      }
    case 10:
      setupStep++;
      if(setSvcNameRequest){
	sprintf(commandbuf, "SS,%s\r", newSvcName);
	writeCommand(commandbuf, "AOK");
	break;
      }
    case 11:
      setupStep++;
      if(setCustomBaudrate){
	// set the baudrate to suit the MSP430 running at 8Mhz
	sprintf(commandbuf, "SZ,%s\r", newBaudrate);
	writeCommand(commandbuf, "AOK");
	break;
      }
    case 12:
      setupStep++;
      if(disableRemoteConfig){
	// disable remote configuration to enhance throughput
	writeCommand("ST,0\r", "AOK");
      }
      else{
	// disable remote configuration to enhance throughput
	writeCommand("ST,60\r", "AOK");
      }
      break;
    case 13:
      setupStep++;
      if(setCustomInquiryTime){
	sprintf(commandbuf, "SI,%s\r", newInquiryTime);
	writeCommand(commandbuf, "AOK");
      }
      else{
	// to save power only leave inquiry on for approx 40msec (every 1.28 secs)
	writeCommand("SI,0040\r", "AOK");
      }
      break;
    case 14:
      setupStep++;
      if(setCustomPagingTime){
	sprintf(commandbuf, "SJ,%s\r", newPagingTime);
	writeCommand(commandbuf, "AOK");
      }
      else{
	// to save power only leave paging on for approx 80msec (every 1.28 secs)
	writeCommand("SJ,0080\r", "AOK");
      }
      break;
    case 15:
      setupStep++;
      // exit command mode
      writeCommand("---\r", "END");
      break;
    default:
      break;
    }
  }  

  command error_t Init.init(){
    TOSH_MAKE_BT_RTS_INPUT();      
    
    TOSH_MAKE_BT_RXD_INPUT();
    TOSH_SEL_BT_RXD_MODFUNC();
    
    // this powers it up on models so equipped, otherwise harmless 
#ifdef BT_PWR_LOGIC_TRUE
    TOSH_SET_SW_BT_PWR_N_PIN();
#else	
    TOSH_CLR_SW_BT_PWR_N_PIN();   
#endif
    
    newMode = FALSE;
    radioMode = SLAVE_MODE;   
    discoverable = TRUE;
    authenticate = FALSE;
    encrypt = FALSE;
    resetDefaultsRequest = FALSE;
    setNameRequest = FALSE;
    setPINRequest = FALSE;
    setSvcClassRequest = FALSE;
    setSvcNameRequest = FALSE;
    setDevClassRequest = FALSE;
    setCustomBaudrate = FALSE;
    disableRemoteConfig = FALSE;
    setCustomInquiryTime = FALSE;
    setCustomPagingTime = FALSE;
    
    setupStep = 0;
    atomic *expectedCommandResponse = 0;   // NULL pointer
    transmissionOverflow = FALSE, messageInProgress = FALSE;

    initRN();
    setupUART();

    return SUCCESS;
  }

  command error_t StdControl.start(){
    TOSH_uwait(15000);
    post runSetCommands();

    return SUCCESS;
  }

  command error_t StdControl.stop(){
    disableRN();
    
#ifdef BT_PWR_LOGIC_TRUE
    TOSH_CLR_SW_BT_PWR_N_PIN();
#else	
    TOSH_SET_SW_BT_PWR_N_PIN();   
#endif
    
    return SUCCESS;
  }
  
  /* after this command is called there will be no link to the connected device */
  command error_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 error_t Bluetooth.connect(uint8_t * addr) {
    char buffer[64];

    sprintf(buffer, "C,%s\r", addr);
    return writeCommand(buffer, "AOK");
  }
     
  async event void 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();
	  atomic *expectedCommandResponse = '\0';
	}
      }
      else
	msg_clear(&incomingMsg);
    }
  }

  async event void UARTData.txDone() {
    if (!transmissionOverflow) {
      post sendNextChar();
    }
  }
    
  // 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 RTSInterrupt.edge(FALSE);
    } 
    else{
      atomic transmissionOverflow = 0;
      post sendNextChar();
      call RTSInterrupt.edge(TRUE);
    }
    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);
    }
    atomic call ConnectionInterrupt.clear();
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -