Demonstrates both master and slave components of a simple remote control, where the input logic state of 8 pins on the BLE master side are sent over a BLE connection and mirrored (output) on the slave side. Think of it as a wireless 8-channel GPIO extension cable.
The master begins scanning on boot and connects to a slave advertising the correct 128-bit service UUID, then performs a GATT discovery to locate the correct service and characteristic handle according to their UUIDs. Once the connection is established, detected GPIO interrupts on P1_x pins (in input mode) trigger a 1-byte GATT write operation to the connected slave, which then writes the same matching logic values to its P1_x pins (in output mode).
NOTE: this demo uses the dual-port rising+falling interrupt technique to effectively achieve "pin change" interrupt behavior. This is accomplished by connecting matching pins on both ports together, e.g. P0_5+P1_5, and P0_6+P1_6, etc. and then configuring the rising edge on one port and falling edge on the other. In this way, GPIO polling can be avoided entirely, and the application uses as little power as possible since the module can sleep between interrupts.
|Safe to Flash:||BLE112, DKBLE112, BLE113, DKBLE113|
|Unsafe to Flash:||BLED112 (no ability to return to DFU mode, no GPIO access)|
BASIC ARCHITECTURAL OVERVIEW:
Raised on boot/reset. This event handler enables relevant interrupt edge detection on desired, pins, then sets scan parameters and initiates a scan with the "gap_discover" command.
Raised when the connection status is updated. This happens when the connection is first established, and the "flags" byte will contain 0x05 in this instance. However, it will also happen if the connected devices bond (i.e. pair), or if encryption is enabled (e.g. with "sm_encrypt_start"), or if either side of the link updates the connection parameters used. Once a connection is established, the script begins a service discovery with the "attclient_read_by_group_type" command.
Raised for each group found during the search started in #3. If the right service is found (matched by UUID), then its start/end handle values are stored for usage later. We cannot use them immediately because the ongoing read-by-group-type procedure must finish first.
Raised for each attribute found during the search started after the service search completes. We look for one specific attribute during this process: the 128-bit UUID designating the GPIO remote control characteristic's data attribute. If/when this is found, it is stored in another variable for use later.
Raised when an attribute client procedure finishes, which in this script means when the "attclient_read_by_group_type" (service search) or the "attclient_find_information" (descriptor search) completes. Since both processes terminate with this same event, we must keep track of the state so we know which one has actually just finished. The completion of the service search will (assuming the service is found) trigger the start of the descriptor search, and the completion of the descriptor search will (assuming the attribute is found) set the correct application state so that GPIO data is sent over the air to the slave when needed.
Raised when a connection is terminated. This is used only to put the BLE device back into a scanning state, essentially starting the process over again.
Raised when a scheduled soft timer interval elapses. This is used only during the connection process to detect if too much time has elapsed since the connection attempt began (4 seconds in this demo). If the timer fires, then the connection attempt is cancelled and the module is returned to the scanning state. The timer is cancelled preemptively if the connection is fully established within 4 seconds.
Raised when a GPIO interrupt occurs. Once the connection is established and all necessary GATT discovery has occurred successfully, GPIO data is written to the GATT server (slave) when necessary. Since the CC254x chipset inside the module does not support CHANGE interrupts, the script enables rising-edge interrupts on P1_x pins and falling-edge interrupts on P0_x pins, and pulls pins on both ports low. Electrically, you can then connect a button (or any signal) to BOTH matching pins on each port (e.g. P0_5 and P1_5), and effectively get "pin change" interrupt data. This configures all 8 available pins to work this way, assuming the following electrical connections:
BASIC ARCHITECTURAL OVERVIEW:
Raised on boot/reset. This event handler sets the desired Port1 pins to OUTPUT mode and initialized them to a logic low state, then puts the module into an advertising/connectable state.
2. connection_status (PLACEHOLDER ONLY, NOT ACTUALLY USED)
Raised when the connection status is updated. This happens when the connection is first established, and the "flags" byte will contain 0x05 in this instance. However, it will also happen if the connected devices bond (i.e. pair), or if encryption is enabled (e.g. with "sm_encrypt_start"), or if either side of the link updates the connection parameters used. This demo does not require any unique behavior based on a new connection.
Raised when a connection is terminated. This is used only to put the BLE device back into an advertising/connectable state.
Raised when a remote GATT client writes a new value to a local GATT characteristic. In this demo, that means that the remote device has sent a new GPIO logic value which we need to apply to our Port1 output pins.