[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