The latest version of the enhanced firmware has changed how the HsOutBuf.OutPtr and HsOutBuf.InPtr fields are updated. The original firmware writes the data out like this:
Code: Select all
void cCommSendHiSpeedData(void)
{
VarsComm.HsModuleOutBuf.OutPtr = 0;
for (VarsComm.HsModuleOutBuf.InPtr = 0; VarsComm.HsModuleOutBuf.InPtr < IOMapComm.HsOutBuf.InPtr; VarsComm.HsModuleOutBuf.InPtr++)
{
VarsComm.HsModuleOutBuf.Buf[VarsComm.HsModuleOutBuf.InPtr] = IOMapComm.HsOutBuf.Buf[IOMapComm.HsOutBuf.OutPtr];
IOMapComm.HsOutBuf.OutPtr++;
}
dHiSpeedSendData(VarsComm.HsModuleOutBuf.Buf, (VarsComm.HsModuleOutBuf.InPtr - VarsComm.HsModuleOutBuf.OutPtr));
}
Notice that if you are comparing the HsOutBuf.OutPtr and the HsOutBuf.InPtr that they will have been updated before the data is completely sent - since the sending doesn't even start to occur until you call dHiSpeedSendData and it isn't actually completed for some number of milliseconds later at slower baud rates. In the enhanced firmware I originally left this function unchanged but currently it looks like this:
Code: Select all
void cCommSendHiSpeedData(void)
{
VarsComm.HsModuleOutBuf.OutPtr = 0;
memcpy(VarsComm.HsModuleOutBuf.Buf, IOMapComm.HsOutBuf.Buf, IOMapComm.HsOutBuf.InPtr);
VarsComm.HsModuleOutBuf.InPtr = IOMapComm.HsOutBuf.InPtr;
dHiSpeedSendData(VarsComm.HsModuleOutBuf.Buf, VarsComm.HsModuleOutBuf.InPtr);
// IOMapComm.HsOutBuf.OutPtr = IOMapComm.HsOutBuf.InPtr;
}
As you can see, I have changed the code to not update the HsOutBuf.OutPtr. The latest code leaves this field unchanged until in cCommCtrl the function dHiSpeedBytesToSend returns zero:
Code: Select all
// update the HsState if there are bytes remaining to be sent
if (IOMapComm.HsState >= HS_BYTES_REMAINING)
{
UWORD bts = 0;
dHiSpeedBytesToSend(&bts);
if (bts == 0)
{
IOMapComm.HsState = HS_DEFAULT;
IOMapComm.HsOutBuf.OutPtr = IOMapComm.HsOutBuf.InPtr;
}
else
IOMapComm.HsState = HS_BYTES_REMAINING + bts;
}
You can see that the IOMapComm.HsState field is now dual-purposed to hold a state value (HS_INITIALISE = 1, HS_INIT_RECEIVER, HS_SEND_DATA, HS_DISABLE, HS_ENABLE, HS_DEFAULT, HS_BYTES_REMAINING = 0x10) as well as the number of bytes remaining to be sent. Just subtract HS_BYTES_REMAINING from HsState if it is >= HS_BYTES_REMAINING.
The proper way to wait for bytes to be sent is to wait until HsState is reset back to HS_DEFAULT but with the latest enhanced firmware you should be able to wait until HsOutBuf.OutPtr is equal to HsOutBuf.InPtr.
The output buffer is always used with HsOutBuf.OutPtr starting at zero which means you write your output data to the first byte in HsOutBuf.Buf and then HsOutBuf.InPtr is set to the number of bytes you are writing. This, however, is not at all how the HsInBuf and its two pointers work. The input buffer is a circular 128 byte buffer. The next incoming byte is written to HsInBuf.Buf at the current value of HsInBuf.InPtr after which InPtr is incremented. This repeats until InPtr reaches 128 and it is reset back to zero.
Code: Select all
for (Tmp = 0; Tmp < NumberOfBytes; Tmp++)
{
IOMapComm.HsInBuf.Buf[IOMapComm.HsInBuf.InPtr] = VarsComm.HsModuleInBuf.Buf[Tmp];
IOMapComm.HsInBuf.InPtr++;
if (IOMapComm.HsInBuf.InPtr > (SIZE_OF_HSBUF - 1))
{
IOMapComm.HsInBuf.InPtr = 0;
}
VarsComm.HsModuleInBuf.Buf[Tmp] = 0;
}
HsInBuf.OutPtr is unchanged as data comes in. It should be updated in a user program to equal InPtr when you have finished reading the data from the circular input buffer. In a compiler that can call new system call functions and you have the enhanced NBC/NXC firmware on your brick then you would just use CommHSRead which will update the HsInBuf.OutPtr field for you but that function does not work right in the standard firmware. So you have to do it yourself. The CommHSRead function also copies the data correctly from the circular buffer which you have to do on your own if you can't use the enhanced NBC/NXC firmware's CommHSRead function.
In any case, I think you've got something fouled up in your code.
John Hansen