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.
- Loading branch information
0 parents
commit 0cabe28
Showing
34 changed files
with
18,722 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
s132_nrf52_6.1.1/* linguist-vendored |
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,27 @@ | ||
Copyright (c) 2019 Ayke van Laethem. All rights reserved. | ||
|
||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions are | ||
met: | ||
|
||
* Redistributions of source code must retain the above copyright | ||
notice, this list of conditions and the following disclaimer. | ||
* Redistributions in binary form must reproduce the above | ||
copyright notice, this list of conditions and the following disclaimer | ||
in the documentation and/or other materials provided with the | ||
distribution. | ||
* Neither the name of the copyright holder nor the names of its | ||
contributors may be used to endorse or promote products derived from | ||
this software without specific prior written permission. | ||
|
||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
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,26 @@ | ||
# Go Bluetooth | ||
|
||
Bluetooth API for embedded devices. | ||
|
||
This package attempts to build a cross-system Bluetooth API written in Go. It | ||
specifically targets embedded devices that are supported by | ||
[TinyGo](https://tinygo.org/). | ||
|
||
At the moment, there is only support for the | ||
[S132](https://www.nordicsemi.com/Software-and-Tools/Software/S132) | ||
SoftDevice (binary driver) on Nordic Semiconductors devices. | ||
|
||
## Flashing the SoftDevice | ||
|
||
Flashing the SoftDevice can be tricky. If you have | ||
[nrfjprog](https://www.nordicsemi.com/Software-and-Tools/Development-Tools/nRF-Command-Line-Tools) | ||
installed, you can erase the flash and flash the new BLE firmware using the | ||
following commands. | ||
|
||
nrfjprog -f nrf52 --eraseall | ||
nrfjprog -f nrf52 --program s132_nrf52_6.1.1/s132_nrf52_6.1.1_softdevice.hex | ||
|
||
After that, don't reset the board but instead flash a new program to it. For | ||
example, you can flash the Heart Rate Sensor example using `tinygo`: | ||
|
||
tinygo flash -target=pca10040-s132v6 ./examples/heartrate |
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,s132v6 | ||
|
||
// 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 "s132_nrf52_6.1.1/s132_nrf52_6.1.1_API/include/nrf_sdm.h" | ||
#include "s132_nrf52_6.1.1/s132_nrf52_6.1.1_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,119 @@ | ||
// +build softdevice,s132v6 | ||
|
||
package bluetooth | ||
|
||
/* | ||
// Define SoftDevice functions as regular function declarations (not inline | ||
// static functions). | ||
#define SVCALL_AS_NORMAL_FUNCTION | ||
#include "s132_nrf52_6.1.1/s132_nrf52_6.1.1_API/include/nrf_sdm.h" | ||
#include "s132_nrf52_6.1.1/s132_nrf52_6.1.1_API/include/ble.h" | ||
#include "s132_nrf52_6.1.1/s132_nrf52_6.1.1_API/include/ble_gap.h" | ||
void assertHandler(void); | ||
*/ | ||
import "C" | ||
|
||
import ( | ||
"device/arm" | ||
"device/nrf" | ||
"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, | ||
} | ||
|
||
var ( | ||
secModeOpen C.ble_gap_conn_sec_mode_t | ||
defaultDeviceName = [6]byte{'T', 'i', 'n', 'y', 'G', 'o'} | ||
) | ||
|
||
// Globally allocated buffer for incoming SoftDevice events. | ||
var eventBuf struct { | ||
C.ble_evt_t | ||
buf [23]byte | ||
} | ||
|
||
func init() { | ||
secModeOpen.set_bitfield_sm(1) | ||
secModeOpen.set_bitfield_lv(1) | ||
} | ||
|
||
// Adapter is a dummy adapter: it represents the connection to the (only) | ||
// SoftDevice on the chip. | ||
type Adapter struct { | ||
} | ||
|
||
// DefaultAdapter is an adapter to the default Bluetooth stack on a given | ||
// target. | ||
var DefaultAdapter = &Adapter{} | ||
|
||
// Enable configures the BLE stack. It must be called before any | ||
// Bluetooth-related calls (unless otherwise indicated). | ||
func (a *Adapter) Enable() error { | ||
// Enable the IRQ that handles all events. | ||
arm.EnableIRQ(nrf.IRQ_SWI2) | ||
arm.SetPriority(nrf.IRQ_SWI2, 192) | ||
|
||
errCode := C.sd_softdevice_enable(&clockConfig, C.nrf_fault_handler_t(C.assertHandler)) | ||
if errCode != 0 { | ||
return Error(errCode) | ||
} | ||
|
||
appRAMBase := uint32(0x200039c0) | ||
errCode = C.sd_ble_enable(&appRAMBase) | ||
if errCode != 0 { | ||
return Error(errCode) | ||
} | ||
|
||
errCode = C.sd_ble_gap_device_name_set(&secModeOpen, &defaultDeviceName[0], uint16(len(defaultDeviceName))) | ||
if errCode != 0 { | ||
return Error(errCode) | ||
} | ||
|
||
var gapConnParams C.ble_gap_conn_params_t | ||
gapConnParams.min_conn_interval = C.BLE_GAP_CP_MIN_CONN_INTVL_MIN | ||
gapConnParams.max_conn_interval = C.BLE_GAP_CP_MIN_CONN_INTVL_MAX | ||
gapConnParams.slave_latency = 0 | ||
gapConnParams.conn_sup_timeout = C.BLE_GAP_CP_CONN_SUP_TIMEOUT_NONE | ||
|
||
errCode = C.sd_ble_gap_ppcp_set(&gapConnParams) | ||
if errCode != 0 { | ||
return Error(errCode) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func handleEvent() { | ||
// TODO: do something with the events. | ||
} | ||
|
||
//go:export SWI2_EGU2_IRQHandler | ||
func handleInterrupt() { | ||
for { | ||
eventBufLen := uint16(unsafe.Sizeof(eventBuf)) | ||
errCode := C.sd_ble_evt_get((*uint8)(unsafe.Pointer(&eventBuf)), &eventBufLen) | ||
if errCode != 0 { | ||
// Possible error conditions: | ||
// * NRF_ERROR_NOT_FOUND: no events left, break | ||
// * NRF_ERROR_DATA_SIZE: retry with a bigger data buffer | ||
// (currently not handled, TODO) | ||
// * NRF_ERROR_INVALID_ADDR: pointer is not aligned, should | ||
// not happen. | ||
// In all cases, it's best to simply stop now. | ||
break | ||
} | ||
handleEvent() | ||
} | ||
} |
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,87 @@ | ||
// +build softdevice,s132v6 | ||
|
||
package bluetooth | ||
|
||
// Error is an error from within the SoftDevice. | ||
type Error uint32 | ||
|
||
func (e Error) Error() string { | ||
switch { | ||
case e < 0x1000: | ||
// Global errors. | ||
switch e { | ||
case 0: | ||
return "no error" | ||
case 1: | ||
return "SVC handler is missing" | ||
case 2: | ||
return "SoftDevice has not been enabled" | ||
case 3: | ||
return "internal error" | ||
case 4: | ||
return "no memory for operation" | ||
case 5: | ||
return "not found" | ||
case 6: | ||
return "not supported" | ||
case 7: | ||
return "invalid parameter" | ||
case 8: | ||
return "invalid state, operation disallowed in this state" | ||
case 9: | ||
return "invalid Length" | ||
case 10: | ||
return "invalid flags" | ||
case 11: | ||
return "invalid data" | ||
case 12: | ||
return "invalid data size" | ||
case 13: | ||
return "operation timed out" | ||
case 14: | ||
return "null pointer" | ||
case 15: | ||
return "forbidden operation" | ||
case 16: | ||
return "bad memory address" | ||
case 17: | ||
return "busy" | ||
case 18: | ||
return "maximum connection count exceeded" | ||
case 19: | ||
return "not enough resources for operation" | ||
default: | ||
return "other global error" | ||
} | ||
case e < 0x2000: | ||
// SDM errors. | ||
switch e { | ||
case 0x1000: | ||
return "unknown LFCLK source" | ||
case 0x1001: | ||
return "incorrect interrupt configuration" | ||
case 0x1002: | ||
return "incorrect CLENR0" | ||
default: | ||
return "other SDM error" | ||
} | ||
case e < 0x3000: | ||
// SoC errors. | ||
return "other SoC error" | ||
case e < 0x4000: | ||
// STK errors. | ||
return "other STK error" | ||
default: | ||
// Other errors. | ||
return "other error" | ||
} | ||
} | ||
|
||
// makeError returns an error (using the Error type) if the error code is | ||
// non-zero, otherwise it returns nil. It is used with internal API calls. | ||
func makeError(code uint32) error { | ||
if code != 0 { | ||
return Error(code) | ||
} | ||
return nil | ||
} |
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,33 @@ | ||
package main | ||
|
||
import ( | ||
"time" | ||
|
||
"github.com/aykevl/go-bluetooth" | ||
) | ||
|
||
// flags + local name | ||
var advPayload = []byte("\x02\x01\x06" + "\x07\x09TinyGo") | ||
|
||
func main() { | ||
adapter := bluetooth.DefaultAdapter | ||
must("enable SD", adapter.Enable()) | ||
adv := adapter.NewAdvertisement() | ||
options := &bluetooth.AdvertiseOptions{ | ||
Interval: bluetooth.NewAdvertiseInterval(100), | ||
} | ||
must("config adv", adv.Configure(advPayload, nil, options)) | ||
must("start adv", adv.Start()) | ||
|
||
println("advertising...") | ||
for { | ||
// Sleep forever. | ||
time.Sleep(time.Hour) | ||
} | ||
} | ||
|
||
func must(action string, err error) { | ||
if err != nil { | ||
panic("failed to " + action + ": " + err.Error()) | ||
} | ||
} |
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,44 @@ | ||
package main | ||
|
||
import ( | ||
"time" | ||
|
||
"github.com/aykevl/go-bluetooth" | ||
) | ||
|
||
// flags + local name | ||
var advPayload = []byte("\x02\x01\x06" + "\x07\x09TinyGo") | ||
|
||
func main() { | ||
println("starting") | ||
adapter := bluetooth.DefaultAdapter | ||
must("enable SD", adapter.Enable()) | ||
adv := adapter.NewAdvertisement() | ||
options := &bluetooth.AdvertiseOptions{ | ||
Interval: bluetooth.NewAdvertiseInterval(100), | ||
} | ||
must("config adv", adv.Configure(advPayload, nil, options)) | ||
must("start adv", adv.Start()) | ||
|
||
must("add service", adapter.AddService(&bluetooth.Service{ | ||
UUID: bluetooth.New16BitUUID(0x180D), // Heart Rate | ||
Characteristics: []bluetooth.Characteristic{ | ||
bluetooth.Characteristic{ | ||
UUID: bluetooth.New16BitUUID(0x2A37), // Heart Rate Measurement | ||
Value: []byte{0, 75}, // 75bpm | ||
}, | ||
}, | ||
})) | ||
|
||
println("sleeping") | ||
for { | ||
// Sleep forever. | ||
time.Sleep(time.Hour) | ||
} | ||
} | ||
|
||
func must(action string, err error) { | ||
if err != nil { | ||
panic("failed to " + action + ": " + err.Error()) | ||
} | ||
} |
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,21 @@ | ||
package bluetooth | ||
|
||
// Advertisement encapsulates a single advertisement instance. | ||
type Advertisement struct { | ||
handle uint8 | ||
} | ||
|
||
// AdvertiseOptions configures everything related to BLE advertisements. | ||
type AdvertiseOptions struct { | ||
Interval AdvertiseInterval | ||
} | ||
|
||
// AdvertiseInterval is the advertisement interval in 0.625µs units. | ||
type AdvertiseInterval uint32 | ||
|
||
// NewAdvertiseInterval returns a new advertisement interval, based on an | ||
// interval in milliseconds. | ||
func NewAdvertiseInterval(intervalMillis uint32) AdvertiseInterval { | ||
// Convert an interval to units of | ||
return AdvertiseInterval(intervalMillis * 8 / 5) | ||
} |
Oops, something went wrong.