diff --git a/part7-bluetooth/README.md b/part7-bluetooth/README.md index d145825..caf1e1d 100644 --- a/part7-bluetooth/README.md +++ b/part7-bluetooth/README.md @@ -104,29 +104,8 @@ The firmware is simply a sequence of HCI commands following this format: We check each HCI command succeeds as we go, wait a second and then return. If it runs without error then we've loaded our firmware and we're ready to start some Bluetooth communications! -The Bluetooth spec ------------------- +Todo +---- -From here, you must tackle the [Bluetooth specification](https://www.bluetooth.com/specifications/bluetooth-core-specification/). You really owe it to yourself to begin with a good understanding of how Bluetooth works - something that is beyond the scope of my write-up! - -I just picked some easy Bluetooth LE commands to implement for our "proof of life" (see the _LE CONTROLLER COMMANDS_ section of the spec): - - * setLEeventmask - * setLEscanenable - * setLEscanparameters - -Read through my implementation alongside the Bluetooth spec - you should see what's going on. Fortunately, these are all we need to start scanning for BLE devices around us. If I can show that I'm seeing other devices, then I've got my proof of life. - -Implementing scanning ---------------------- - -If you look in _kernel.c_, you'll see the main bulk of our scanning code. Exactly as we described above, we first reset the chip, then load the firmware. After that, we set the LE event mask (tell the chip what we want to be notified about) and start scanning for events. `bt_update()` then polls the chip to see if any events are awaiting our attention. - -There may be one or more **ad report** in each event, and each contains the 48-bit Bluetooth address of the associated device e.g. `AA:BB:CC:DD:EE:FF` (bd_addr) as well as the data. I found a great article on the [Advertising Data Format from Silicon Labs](https://www.silabs.com/community/wireless/bluetooth/knowledge-base.entry.html/2017/02/10/bluetooth_advertisin-hGsf). Reading this will help you interpret my decode routines. - -Right now, I'm just printing the bd_addr (using the convenient `uart_hex` routine added to _io.c_), the ad report type & length, and the friendly/full device name if received (ad_type 0x08/0x09 respectively). - -Proof of life! --------------- - -And, when I build and run this, I see reports coming in from my neighbouring Bluetooth speaker - magic! _This is our first step towards low-level Bluetooth control of the RPi4._ + * Write up scanning implementation (receiving advertising reports) + * Write up advertising implementation (simple Eddystone Beacon) diff --git a/part7-bluetooth/bt.c b/part7-bluetooth/bt.c index 31c8b4c..31cf5a8 100644 --- a/part7-bluetooth/bt.c +++ b/part7-bluetooth/bt.c @@ -39,6 +39,7 @@ void bt_writeByte(char byte) { while ((mmio_read(ARM_UART0_FR) & 0x20) != 0); mmio_write(ARM_UART0_DR, (unsigned int)byte); + uart_byte(byte); } void bt_flushrx() @@ -74,15 +75,17 @@ enum { OGF_LE_CONTROL = 0x08, OGF_VENDOR = 0x3f, + COMMAND_SET_BDADDR = 0x01, COMMAND_RESET_CHIP = 0x03, + COMMAND_SET_BAUD = 0x18, COMMAND_LOAD_FIRMWARE = 0x2e, HCI_COMMAND_PKT = 0x01, HCI_EVENT_PKT = 0x04, - COMMAND_COMPLETE_CODE = 0x0e, - LL_SCAN_ACTIVE = 0x01 + LL_SCAN_ACTIVE = 0x01, + LL_ADV_NONCONN_IND = 0x03 }; unsigned char empty[] = {}; @@ -91,12 +94,15 @@ int hciCommandBytes(unsigned char *opcodebytes, unsigned char *data, unsigned ch { unsigned char c=0; + uart_writeText("HCI_START\n"); bt_writeByte(HCI_COMMAND_PKT); bt_writeByte(opcodebytes[0]); bt_writeByte(opcodebytes[1]); bt_writeByte(length); + uart_writeText("\n______ DATA:\n"); while (c++=0;c-=4) { + // get highest tetrad + n=(b>>c)&0xF; + // 0-9 => '0'-'9', 10-15 => 'A'-'F' + n+=n>9?0x37:0x30; + + uart_writeByteBlockingActual(n); + } + uart_writeByteBlockingActual(' '); +} diff --git a/part7-bluetooth/io.h b/part7-bluetooth/io.h index 42feb04..8547cc0 100644 --- a/part7-bluetooth/io.h +++ b/part7-bluetooth/io.h @@ -11,3 +11,4 @@ void mmio_write(long reg, unsigned int val); unsigned int mmio_read(long reg); void gpio_useAsAlt3(unsigned int pin_number); void uart_hex(unsigned int d); +void uart_byte(unsigned char b); diff --git a/part7-bluetooth/kernel.c b/part7-bluetooth/kernel.c index d2dda0f..9a0e88a 100644 --- a/part7-bluetooth/kernel.c +++ b/part7-bluetooth/kernel.c @@ -60,17 +60,6 @@ unsigned char *poll() return 0; } -void print_bdaddr(long bd_addr) -{ - unsigned char byte; - - for (int c=9;c>=4;c--) { - byte = (unsigned char)((bd_addr >> ((c-4)*8) & 0xff)); - uart_hex(byte); - if (c != 4) uart_writeText(":"); - } -} - void bt_update() { unsigned char *buf; @@ -132,8 +121,27 @@ void main() uart_writeText("bt_loadfirmware()\n"); bt_loadfirmware(); + uart_writeText("bt_setbaud()\n"); + bt_setbaud(); + + uart_writeText("bt_setbdaddr()\n"); + bt_setbdaddr(); + + /* + uart_writeText("startActiveScanning()\n"); setLEeventmask(0xff); startActiveScanning(); + */ + + unsigned char local_addr[6]; + uart_writeText("bt_getbdaddr()\n"); + bt_getbdaddr(local_addr); + uart_writeText("\nBD_ADDR is "); + for (int c=5;c>=0;c--) uart_byte(local_addr[c]); + uart_writeText("\n"); + + uart_writeText("startActiveAdvertising()\n"); + startActiveAdvertising(); uart_writeText("Waiting for input...\n"); while (1) {