After a brief holiday I am back and documenting what I was working on literally hours before needing to go. Problem solving can be addictive.:-)
Just before I went I thought I would test the scanning for BLE devices, like the BLE keyring I am using in the project, and it did not work. I was getting nothing. The summary is that I needed to upload a firmware update to the CC256xB in the PAN1326B module at boot to access the BLE functions.
At first I decided to experiment with the BTStack solution that has the patch pre-rendered in the open source code, and after a little experimentation I was able to send these blocks, but timing was critical and I needed to implement a form of flow control to make this reliable.
For reference I am wanting to avoid BTStack as it adds so much complexity to my project when I only need a fraction of its functionality. There is nothing wrong with BTStack, and following other threads here I may be the only person not using it for my project, it is just not the best fit for this project..
In the end I used the library from https://www.ti.com/tool/CC256XB-BT-SP and created code to read each HCI block and send to the module, and then wait for a response before sending the next.
To my surprise this worked without any great complication, but it was still not scanning for BLE devices. Then thank to BigG for finding the magic HCI commands. I was getting data. I believe I missed that I needed to activate the old school Bluetooth functionality before activating the Low Energy functionality, but I have not yet tested that.
Here is some test code. I should have it tidied by the time the full project is ready.
First I downloaded cc256xb_bt_sp_v1.8.zip from the TI link above. I then took BasePatch (including the part in the #ifdef __SUPPORT_LOW_ENERGY__ block) and LowEnergyPatch from CC256XB.h. Do not take the AvprPatch though. I then load that into a const uint8_t.
const uint8_t patchBinary[] = { 0x01,0x37,0xfe,0x02,0x07,0x10…
Next I add my commands to the bottom to start the scan. I could, and in a different scenario would, send these separately, but for this project this gives me little advantage.
// Set Event Mask 0x01, 0x01, 0x0C, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // Set LE Event Mask 0x01, 0x01, 0x20, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // Set Enable LE 0x01, 0x6D, 0x0C, 0x02, 0x01, 0x01, // Set Scan Parameters 0x01, 0x0B, 0x20, 0x07, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0x00, // Set Scan Enable (aka Start) 0x01, 0x0C, 0x20, 0x02, 0x01, 0x00
The code simply iterates thought the data and waits for a response at the end of each HCI command.
uint16_t cursor = 0;
while (cursor < totalSize) {
BT_SERIAL.write(pgm_read_byte(&patchBinary[cursor++])); // Command (should always be 0x01)
BT_SERIAL.write(pgm_read_byte(&patchBinary[cursor++])); // Opcode Low
BT_SERIAL.write(pgm_read_byte(&patchBinary[cursor++])); // Opcode High
uint8_t blockSize = pgm_read_byte(&patchBinary[cursor++]); // Read the size of the block
BT_SERIAL.write(blockSize);
for (int i=0; i<blockSize; i++) {
BT_SERIAL.write(pgm_read_byte(&patchBinary[cursor++]));
}
// Wait for a response
receiveHCIResponse(BT_SERIAL);
}
The code that does the reading of the response still needs some tidying and functionality adding, but here it is as it stands.
int streamReadBlocking(Stream &inSerial, int inTimeout = HCI_TIMEOUT) {
unsigned long waitEnd = millis() + inTimeout;
while ( ( !inSerial.available() ) && ( waitEnd>millis() ) ) {
delay(1);
}
return BT_SERIAL.read();
}
void receiveHCIResponse(Stream &inSerial) {
uint8_t packetType = streamReadBlocking(inSerial);
uint8_t eventCode = streamReadBlocking(inSerial);
uint8_t paramLength = streamReadBlocking(inSerial);
// Skip what we don't need
streamSkipBlocking(inSerial, paramLength, HCI_TIMEOUT);
}
There was still one issue, that being I was getting incomplete messages back from the module. I was getting packets of data reporting to have many many messages in it, but in fact only had one to two. My code was timing out and nothing was making any sense.
In the end I instigated the scan (aka ran the Set Scan Enable command) with the remove duplicates flag set to 1 ("0x01, 0x0C, 0x20, 0x02, 0x01, 0x01"). This just worked and I now get several properly formed messages a minute. All the local BLE devices are showing up, and are repeated between 1 and 2 minutes, so adequate for my needs.
I will note that buffer overruns should be considered with this approach. I am not so worried at the moment as binary data being read from flash is fixed at compile time and not stored in RAM, and I do not trust the data received from the module to use it for checking a buffer size, but it really does need considering.
So that is working and I am at the point in starting the final “integration hell” stage of the project. Wish me luck.