I may not understand what you are saying about full-duplex vs half-duplex wrt Bluetooth communication in the standard NXT firmware vs the RobotC firmware. It is certain that the standard firmware is fully capable of writing from a slave to a master on connection 0 whenever it wants to. That is precisely what happens when a direct command comes into the Comm module from a PC. The slave NXT creates a packet of data and it writes it to the Bluetooth output buffer for connection 0 and sends the response to the PC.
I just had a browse through the source code in c_cmd.c and c_comm.c and as far as I can see there is absolutely nothing there that would stop a program running on a slave from writing a message via Bluetooth over connection 0 to its master. The system call CommBTWrite takes a connection number from 0 to 3.
Code: Select all
//cCmdWrapCommBTWrite
//ArgV[0]: (return) Status byte, SBYTE
//ArgV[1]: Connection index, 0-3
//ArgV[2]: Buffer
//
NXT_STATUS cCmdWrapCommBTWrite(UBYTE * ArgV[])
{
SBYTE * pReturnVal = (SBYTE*)(ArgV[0]);
UBYTE Connection = *(ArgV[1]);
UBYTE * pBuf;
UWORD BufLength;
DV_INDEX DVIndex;
//Resolve array arguments
DVIndex = *(DV_INDEX *)(ArgV[2]);
pBuf = cCmdDVPtr(DVIndex);
BufLength = DV_ARRAY[DVIndex].Count;
//If there's an old error code hanging around, clear it before proceeding.
if (VarsCmd.CommStat < 0)
VarsCmd.CommStat = SUCCESS;
//!!! Only first 256 bytes could possibly make it through! Should return error on longer input?
//!!! Not requesting a wait-for-response because only known use doesn't read responses.
pMapComm->pFunc(SENDDATA, (UBYTE)BufLength, Connection, FALSE, pBuf, (UWORD*)&(VarsCmd.CommStat));
//!!! Reasonable to wrap below code in cCmdCommBTCheckStatus?
//INPROGRESS means our request was accepted by His Funkiness of pFunc
if (VarsCmd.CommStat == (SWORD)INPROGRESS)
{
*pReturnVal = STAT_COMM_PENDING;
//Set DirtyComm flag so stream is reset after program ends
VarsCmd.DirtyComm = TRUE;
}
//Translate BTBUSY to ERR_COMM_CHAN_NOT_READY
else if (VarsCmd.CommStat == (SWORD)BTBUSY)
{
*pReturnVal = ERR_COMM_CHAN_NOT_READY;
}
else
{
*pReturnVal = UNPACK_STATUS(VarsCmd.CommStat);
}
return (NO_ERR);
}
It passes the connection number and the outbound buffer data to the Comm module's SENDDATA function. Here's the relevant code from c_comm.c:
Code: Select all
case SENDDATA:
{
/* Param2 indicates the port that the data should be */
/* be sent on - param1 indicates the number of data */
/* to be sent. pName is the pointer to the data */
if (Param1 <= sizeof(VarsComm.BtModuleOutBuf.Buf))
{
if ('\0' != IOMapComm.BtConnectTable[Param2].Name[0])
{
VarsComm.BtCmdData.ParamOne = Param1;
VarsComm.BtCmdData.ParamTwo = Param2;
VarsComm.BtCmdData.ParamThree = Param3;
memcpy((VarsComm.BtModuleOutBuf.Buf), pName, Param1);
VarsComm.ActiveUpdate = UPD_SENDDATA;
}
else
{
ReturnVal = (UWORD)ERR_COMM_CHAN_NOT_READY;
ReturnVal |= 0x8000;
}
}
else
{
ReturnVal = (UWORD)ERR_COMM_BUFFER_FULL;
ReturnVal |= 0x8000;
}
}
break;
In the case for handling UPD_SENDDATA it calls dBtSendMsg once the stream is open (which it may already be). This function is exactly the same routine that the firmware calls to send out the response message to any direct or system command that the firmware automatically handles under the hood.
Again, I could be wrong, but to the best of my knowledge the only "half-duplex" thing in the standard firmware related to Bluetooth messaging is the design of the standard NXT firmware's mailbox system and its associated protocol for sending mailbox messages between two NXTs. In the standard firmware's design of the mailbox system a slave NXT never sends a message directly to a mailbox on the master NXT. Instead it writes to a local response mailbox and the master NXT has to poll a slave NXT for a message. This is the kind of behavior that you were describing in your original response on this thread. But - again to my knowledge - that is strictly limited to the mailbox system and not to Bluetooth communication in general.
One thing that the RobotC firmware may do better/differently than the standard NXT firmware is optimize how and when it switches the Bluetooth subsystem (which is exactly the same for both firmwares) between command mode and data mode. Since switching back and forth is time-consuming the better you manage this state the more optimal you can communicate via Bluetooth. In the standard NXT firmware, though, this normally only becomes an issue when you have multiple connections that you need to send data over. To switch from one connection to another you have to close and reopen a stream to the new connection and that requires switching from data mode to command mode and then back to data mode again. I believe that is one of the reasons why the RobotC firmware (from what I have gathered) only allows one slave at a time.
A Bluetooth connection with an active stream is, to my knowledge, a bi-direction (aka full-duplex) serial port. Here's a quote from
http://wiresareobsolete.com/wordpress/2 ... th-rfcomm/ that seems to back me up:
RFCOMM is a layer of the Bluetooth Protocol Stack that provides serial data transfer services (via “socketsâ€). It is the base of many of the common profiles such as Dialup Networking (DUN) and Serial Port Profile (SPP). In essence, though, it is a way for developers to create a full duplex serial data stream between two points.
John Hansen