forked from tinygo-org/bluetooth
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add S110 version 8.0.0 SoftDevice for nrf51822
The nrf51822 chip is still widely available, for example in the BBC micro:bit. Therefore it's a good idea to support it too. Unfortunately, Nordic decided to change the API in some significant ways so many parts are not compatible between S110 for nrf51 and the other nrf52* SoftDevices.
- Loading branch information
Showing
29 changed files
with
11,633 additions
and
151 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
// +build softdevice,s110v8 | ||
|
||
package bluetooth | ||
|
||
/* | ||
// Define SoftDevice functions as regular function declarations (not inline | ||
// static functions). | ||
#define SVCALL_AS_NORMAL_FUNCTION | ||
#include "nrf_sdm.h" | ||
#include "ble.h" | ||
#include "ble_gap.h" | ||
void assertHandler(void); | ||
*/ | ||
import "C" | ||
|
||
import "unsafe" | ||
|
||
//export assertHandler | ||
func assertHandler(pc uint32, line_number uint16, p_file_name *byte) { | ||
println("SoftDevice assert") | ||
} | ||
|
||
func (a *Adapter) enable() error { | ||
// Enable the SoftDevice. | ||
errCode := C.sd_softdevice_enable(C.NRF_CLOCK_LFCLKSRC_RC_250_PPM_250MS_CALIBRATION, C.softdevice_assertion_handler_t(C.assertHandler)) | ||
if errCode != 0 { | ||
return Error(errCode) | ||
} | ||
|
||
// Enable the BLE stack. | ||
enableParams := C.ble_enable_params_t{ | ||
gatts_enable_params: C.ble_gatts_enable_params_t{ | ||
attr_tab_size: C.BLE_GATTS_ATTR_TAB_SIZE_DEFAULT, | ||
}, | ||
} | ||
errCode = C.sd_ble_enable(&enableParams) | ||
return makeError(errCode) | ||
} | ||
|
||
func handleEvent() { | ||
id := eventBuf.header.evt_id | ||
switch { | ||
case id >= C.BLE_GAP_EVT_BASE && id <= C.BLE_GAP_EVT_LAST: | ||
gapEvent := eventBuf.evt.unionfield_gap_evt() | ||
switch id { | ||
case C.BLE_GAP_EVT_CONNECTED: | ||
handler := defaultAdapter.handler | ||
if handler != nil { | ||
handler(&ConnectEvent{GAPEvent: GAPEvent{Connection(gapEvent.conn_handle)}}) | ||
} | ||
case C.BLE_GAP_EVT_DISCONNECTED: | ||
handler := defaultAdapter.handler | ||
if handler != nil { | ||
handler(&DisconnectEvent{GAPEvent: GAPEvent{Connection(gapEvent.conn_handle)}}) | ||
} | ||
case C.BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: | ||
// Respond with the default PPCP connection parameters by passing | ||
// nil: | ||
// > If NULL is provided on a peripheral role, the parameters in the | ||
// > PPCP characteristic of the GAP service will be used instead. If | ||
// > NULL is provided on a central role and in response to a | ||
// > BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST, the peripheral request | ||
// > will be rejected | ||
C.sd_ble_gap_conn_param_update(gapEvent.conn_handle, nil) | ||
default: | ||
if debug { | ||
println("unknown GAP event:", id) | ||
} | ||
} | ||
case id >= C.BLE_GATTS_EVT_BASE && id <= C.BLE_GATTS_EVT_LAST: | ||
gattsEvent := eventBuf.evt.unionfield_gatts_evt() | ||
switch id { | ||
case C.BLE_GATTS_EVT_WRITE: | ||
writeEvent := gattsEvent.params.unionfield_write() | ||
len := writeEvent.len - writeEvent.offset | ||
data := (*[255]byte)(unsafe.Pointer(&writeEvent.data[0]))[:len:len] | ||
handler := defaultAdapter.getCharWriteHandler(writeEvent.handle) | ||
if handler != nil { | ||
handler.callback(Connection(gattsEvent.conn_handle), int(writeEvent.offset), data) | ||
} | ||
case C.BLE_GATTS_EVT_SYS_ATTR_MISSING: | ||
// This event is generated when reading the Generic Attribute | ||
// service. It appears to be necessary for bonded devices. | ||
// From the docs: | ||
// > If the pointer is NULL, the system attribute info is | ||
// > initialized, assuming that the application does not have any | ||
// > previously saved system attribute data for this device. | ||
// Maybe we should look at the error, but as there's not really a | ||
// way to handle it, ignore it. | ||
C.sd_ble_gatts_sys_attr_set(gattsEvent.conn_handle, nil, 0, 0) | ||
default: | ||
if debug { | ||
println("unknown GATTS event:", id, id-C.BLE_GATTS_EVT_BASE) | ||
} | ||
} | ||
default: | ||
if debug { | ||
println("unknown event:", id) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
// +build softdevice,!s110v8 | ||
|
||
package bluetooth | ||
|
||
/* | ||
// Define SoftDevice functions as regular function declarations (not inline | ||
// static functions). | ||
#define SVCALL_AS_NORMAL_FUNCTION | ||
#include "nrf_sdm.h" | ||
#include "ble.h" | ||
#include "ble_gap.h" | ||
void assertHandler(void); | ||
*/ | ||
import "C" | ||
|
||
import "unsafe" | ||
|
||
//export assertHandler | ||
func assertHandler() { | ||
println("SoftDevice assert") | ||
} | ||
|
||
var clockConfig C.nrf_clock_lf_cfg_t = C.nrf_clock_lf_cfg_t{ | ||
source: C.NRF_CLOCK_LF_SRC_SYNTH, | ||
rc_ctiv: 0, | ||
rc_temp_ctiv: 0, | ||
accuracy: 0, | ||
} | ||
|
||
func (a *Adapter) enable() error { | ||
// Enable the SoftDevice. | ||
errCode := C.sd_softdevice_enable(&clockConfig, C.nrf_fault_handler_t(C.assertHandler)) | ||
if errCode != 0 { | ||
return Error(errCode) | ||
} | ||
|
||
// Enable the BLE stack. | ||
appRAMBase := uint32(0x200039c0) | ||
errCode = C.sd_ble_enable(&appRAMBase) | ||
return makeError(errCode) | ||
} | ||
|
||
func handleEvent() { | ||
id := eventBuf.header.evt_id | ||
switch { | ||
case id >= C.BLE_GAP_EVT_BASE && id <= C.BLE_GAP_EVT_LAST: | ||
gapEvent := eventBuf.evt.unionfield_gap_evt() | ||
switch id { | ||
case C.BLE_GAP_EVT_CONNECTED: | ||
handler := defaultAdapter.handler | ||
if handler != nil { | ||
handler(&ConnectEvent{GAPEvent: GAPEvent{Connection(gapEvent.conn_handle)}}) | ||
} | ||
case C.BLE_GAP_EVT_DISCONNECTED: | ||
handler := defaultAdapter.handler | ||
if handler != nil { | ||
handler(&DisconnectEvent{GAPEvent: GAPEvent{Connection(gapEvent.conn_handle)}}) | ||
} | ||
case C.BLE_GAP_EVT_ADV_REPORT: | ||
advReport := gapEvent.params.unionfield_adv_report() | ||
if debug && &scanReportBuffer.data[0] != advReport.data.p_data { | ||
// Sanity check. | ||
panic("scanReportBuffer != advReport.p_data") | ||
} | ||
// Prepare the globalScanResult, which will be passed to the | ||
// callback. | ||
scanReportBuffer.len = byte(advReport.data.len) | ||
globalScanResult.RSSI = int16(advReport.rssi) | ||
globalScanResult.Address = advReport.peer_addr.addr | ||
globalScanResult.AdvertisementPayload = &scanReportBuffer | ||
// Signal to the main thread that there was a scan report. | ||
// Scanning will be resumed (from the main thread) once the scan | ||
// report has been processed. | ||
gotScanReport.Set(1) | ||
case C.BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: | ||
// Respond with the default PPCP connection parameters by passing | ||
// nil: | ||
// > If NULL is provided on a peripheral role, the parameters in the | ||
// > PPCP characteristic of the GAP service will be used instead. If | ||
// > NULL is provided on a central role and in response to a | ||
// > BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST, the peripheral request | ||
// > will be rejected | ||
C.sd_ble_gap_conn_param_update(gapEvent.conn_handle, nil) | ||
case C.BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST: | ||
// We need to respond with sd_ble_gap_data_length_update. Setting | ||
// both parameters to nil will make sure we send the default values. | ||
C.sd_ble_gap_data_length_update(gapEvent.conn_handle, nil, nil) | ||
default: | ||
if debug { | ||
println("unknown GAP event:", id) | ||
} | ||
} | ||
case id >= C.BLE_GATTS_EVT_BASE && id <= C.BLE_GATTS_EVT_LAST: | ||
gattsEvent := eventBuf.evt.unionfield_gatts_evt() | ||
switch id { | ||
case C.BLE_GATTS_EVT_WRITE: | ||
writeEvent := gattsEvent.params.unionfield_write() | ||
len := writeEvent.len - writeEvent.offset | ||
data := (*[255]byte)(unsafe.Pointer(&writeEvent.data[0]))[:len:len] | ||
handler := defaultAdapter.getCharWriteHandler(writeEvent.handle) | ||
if handler != nil { | ||
handler.callback(Connection(gattsEvent.conn_handle), int(writeEvent.offset), data) | ||
} | ||
case C.BLE_GATTS_EVT_SYS_ATTR_MISSING: | ||
// This event is generated when reading the Generic Attribute | ||
// service. It appears to be necessary for bonded devices. | ||
// From the docs: | ||
// > If the pointer is NULL, the system attribute info is | ||
// > initialized, assuming that the application does not have any | ||
// > previously saved system attribute data for this device. | ||
// Maybe we should look at the error, but as there's not really a | ||
// way to handle it, ignore it. | ||
C.sd_ble_gatts_sys_attr_set(gattsEvent.conn_handle, nil, 0, 0) | ||
case C.BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: | ||
// This event is generated by some devices. While we could support | ||
// larger MTUs, this default MTU is supported everywhere. | ||
C.sd_ble_gatts_exchange_mtu_reply(gattsEvent.conn_handle, C.BLE_GATT_ATT_MTU_DEFAULT) | ||
default: | ||
if debug { | ||
println("unknown GATTS event:", id, id-C.BLE_GATTS_EVT_BASE) | ||
} | ||
} | ||
default: | ||
if debug { | ||
println("unknown event:", id) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// +build softdevice,s110v8 | ||
|
||
// This file is necessary to define SVCall wrappers, because TinyGo does not yet | ||
// support static functions in the preamble. | ||
|
||
// Discard all 'static' attributes to define functions normally. | ||
#define static | ||
|
||
#include "s110_nrf51_8.0.0/s110_nrf51_8.0.0_API/include/nrf_sdm.h" | ||
#include "s110_nrf51_8.0.0/s110_nrf51_8.0.0_API/include/ble.h" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// +build softdevice,s110v8 | ||
|
||
package bluetooth | ||
|
||
/* | ||
// Add the correct SoftDevice include path to CFLAGS, so #include will work as | ||
// expected. | ||
#cgo CFLAGS: -Is110_nrf51_8.0.0/s110_nrf51_8.0.0_API/include | ||
*/ | ||
import "C" |
Oops, something went wrong.