Skip to content

Commit

Permalink
Merge branch 'sdk-8-support'
Browse files Browse the repository at this point in the history
  • Loading branch information
trond-snekvik committed Apr 19, 2016
2 parents c9dc33f + 5c67e57 commit 6d2c36a
Show file tree
Hide file tree
Showing 197 changed files with 72,060 additions and 10,197 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
*.uvoptx binary
*.uvopt binary
*.map -crlf
*.sh eol=lf
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
*.map
*.tra
*.dep
*._2i
*.l2p
*.__i
*.fed
*.crf
*.d
*.o
Expand All @@ -20,3 +23,5 @@
*.uvguix.*
*.tmp
**/arm/JLinkLog.txt
**/_viminfo
**/_vimtags
124 changes: 79 additions & 45 deletions README.adoc
Original file line number Diff line number Diff line change
@@ -1,78 +1,98 @@
= nRF51-ble-broadcast-mesh
= nRF OpenMesh (formerly nRF51-ble-broadcast-mesh)

Bluetooth Low Energy based rebroadcasting mesh implementation on the nRF51.
Works with SoftDevice S110 v7.x with Timeslot API (tested), likely to work with
S120 and S130 SoftDevices (not tested). Support for both SDK6.x.x and SDK7.x.x as of release v0.6.1.
Bluetooth Low Energy based rebroadcasting mesh implementation on the nRF51 called *nRF OpenMesh*.
Works with SoftDevice S110 v8.x and S130 v1.0 with Timeslot API, and the nRF51 SDK8.1.
Offers an API for implementing your own mesh enabled application, operating
concurrently with regular BLE applications.

*NOTE:* The master branch is currently parked, and lacks some critical features compared to the latest version of the mesh
framework. Currently, the link:../../tree/sdk-8-support[sdk-8-support] branch contains the latest updates, but you can always check the "Releases" tab above to keep track of all the latest versions. We will move back into the master branch in the future.

== About
This project was created in collaboration with The Norwegian University of
Science and Technology (NTNU), as part of a master thesis. The project is not
part of the official Nordic Semiconductor SDK. Developers are welcome to contribute
and provide feedback.

== Usage
In addition to two provided examples, there is a template project under
_nRF51/examples/_. This may be used as a basis for your own applications, or you
could choose to do it yourself from scratch. In theory, the framework should be
compatible with most SoftDevice based projects, but some restrictions to
hardware and software modules apply, see link:docs/how_it_works.adoc#resource-allocation[Resource allocation] for details.
The framework adds a Mesh GATT service to the SoftDevice GATT server which
contain all mesh-global states. This service may be accessed by external nodes,
just as any other GATT service, through a connection established via the
SoftDevice. See section link:docs/how_it_works.adoc#gatt-service[GATT service] for details about structure and
access.
hardware and software modules apply, see
link:docs/how_it_works.adoc#resource-allocation[Resource allocation] for
details. The framework adds a Mesh GATT service to the SoftDevice GATT server
which contain all mesh-global states. This service may be accessed by external
nodes, just as any other GATT service, through a connection established via the
SoftDevice. See section link:docs/how_it_works.adoc#gatt-service[GATT service]
for details about structure and access.

=== Serial interface

The framework also has support for external control via SPI. The serial interface is based on the nRF8001 SPI interface, with different opcodes. An application controller framework is available under _application_controller_, with an Arduino example to get you started. Note that the application controller requires the https://github.com/NordicSemiconductor/ble-sdk-arduino[ble-sdk-arduino] framework. This allows you to operate an Arduino along with an nRF51 dev kit in the mesh, making it easier to create mesh applications. Each nRF51 example project has a separate target (named "nRF51822 xxAA serial") that incorporates the serial interface with the rest of the project.
The framework also has support for external control via SPI or UART. The serial
interface is based on the nRF8001 SPI interface, with different opcodes. An
application controller framework using SPI is available under
_application_controller_, with an Arduino example to get you started. Note
that the application controller requires the
https://github.com/NordicSemiconductor/ble-sdk-arduino[ble-sdk-arduino]
framework. This allows you to operate an Arduino along with an nRF51 dev kit
in the mesh, making it easier to create mesh applications. Each nRF51 example
project has a separate target (named "nRF51822 xxAA serial") that incorporates
the serial interface with the rest of the project.

=== Getting started

The framework supports both nRF51 SDK 6.x.x and nRF51 SDK 7.x.x. Since the structure of the SDK changed between these versions, you have to clone the repo differently based on which version you utilize.

If you're using 6.x.x, clone the repository into _<SDK6-folder>/nRF51822/boards/PCA10001/S110/<Project-folder>_.
The framework requires nRF51 SDK 8.1, and can be built with both Keil uVision
and GCC-arm-none-eabi.

The SDK 7.x.x projects utilizes the *non-pack* version of the SDK, available at http://developer.nordicsemi.com/[Nordic Semiconductor's developer portal]. Clone this repo into _<SDK7-folder>/examples/<Project-folder>_.
The example projects utilizes the *non-pack* version of the SDK, available
at http://developer.nordicsemi.com/[Nordic Semiconductor's developer portal].
Clone this repo into _<SDK8-folder>/examples/<Project-folder>_.

This will ensure that all references to the SDK are correctly placed, so that you don't have to change all references to the SDK in the project files. If you still want to clone the repo into a different folder than suggested, you need to change the location of all the files under the _Lib_ group in Keil uVision, in addition to the include paths under the menu _Target options -> C/C++ -> Include Paths_.
This will ensure that all references to the SDK are correctly placed, so that
you don't have to change all references to the SDK in the project files. If
you still want to clone the repo into a different folder than suggested, you
need to change the location of all the files under the _Lib_ group in Keil
uVision, in addition to the include paths under the menu
_Target options -> C/C++ -> Include Paths_ (or in the project-local
makefiles for GCC).

=== Integrating with existing applications
The framework is built to be compatible with most existing SDK example projects, and we've written a short guide to include it in existing projects with as few changes to existing code as possible. The guide uses the ble_app_proximity example from the SDK as reference, and shows a step by step approach to overcoming typical problems with integration:
The framework is built to be compatible with most existing SDK example
projects, and as of v0.6.9, it is also compatible with the SDK module
APP_TIMER right out of the box.
In order to be compatible with the APP_TIMER module, the framework makes
use of the Quadrature Decoder hardware interrupt handler for asynchronous
processing.
Applications which already use this hardware module must be altered to
use a different interrupt for mesh processing. All async-behavior is
contained in the _event_handler.c_ file.

We've written a short guide to include it in existing projects with as
few changes to existing code as possible. The guide uses the ble_app_proximity
example from the SDK as reference, and shows a step by step approach to
overcoming typical problems with integration:

link:docs/integrating_w_SD_apps.adoc[Guide to integrating rbc_mesh into existing projects]

== Basic concepts

A rebroadcasting mesh network works by flooding all messages to all nodes
A rebroadcasting mesh network works by flooding all messages to all nodes
in the network through broadcasts. Each time a device receives a broadcast
message from some other device in the mesh, it repeats the message, or
_rebroadcasts_ it, letting its neighbors hear the new message.
message from some other device in the mesh, it repeats the message, or
_rebroadcasts_ it, letting its neighbors hear the new message.
The neighbors rebroadcast the message to their neighbors, and the process
is repeated until all devices in the mesh have received the message. This
lets wireless devices talk to each other without being within direct radio
is repeated until all devices in the mesh have received the message. This
lets wireless devices talk to each other without being within direct radio
range, as devices between them help relaying the messages.

The Rebroadcasting Mesh framework (hereby referred to as "the framework" or
rbc_mesh) provides a connection-less, rebroadcasting infrastructure for
synchronizing states across a set of BLE enabled nodes. All nodes receive all
messages that are transmitted within their range, and any node may update the
mesh-global states. There is no hierarchy, and no directed data links.
mesh-global states. There is no hierarchy, and no directed data links.

The framework resides on top of the nRF51 SoftDevice, utilizing the Timeslot
API to allocate radio time. The framework will attempt to allocate as much time
as possible, in order to listen for other nodes' messages.

All nodes in the mesh share a set of indexed data slots. The data contained at each
index is propagated through the mesh with version numbers, with the objective of
synchronizing the same version of the data across all nodes in the mesh. Each
time a node overwrites a value, it increments the version number, and all nodes
that receive a broadcast message with a version number that is higher than the
one in its database, will adapt this new version of the value.
index is propagated through the mesh with version numbers, with the objective of
synchronizing the same version of the data across all nodes in the mesh. Each
time a node overwrites a value, it increments the version number, and all nodes
that receive a broadcast message with a version number that is higher than the
one in its database, will adapt this new version of the value.

The value propagation is controlled by an implementation of the IETF RFC6206
"Trickle", a flood control algorithm for lossy, low power networks. The Trickle
Expand All @@ -82,26 +102,40 @@ update to the state it manages was. The Trickle algorithm dynamically adapts to
node density and value update frequency.

The framework provides each handle-value pair with one Trickle-instance (an
isolated version of the algorithm), and utilizes the SoftDevice GATT server
structure to store the values. All values are stored as characteristics within
one "Mesh"-GATT Service, which is accessible to external nodes through a
classic BLE SoftDevice connection, implemented in application space. The "BLE
Gateway example" displays a way to achieve such behavior.
isolated version of the algorithm), and utilizes a Least-recently-used cache-
system to store the values. When a value falls out of the "data cache", the device
stops retransmitting it, and when the value falls out of the larger "handle cache",
the device also forgets which version of the value it saw last.

The mesh can be interfaced by regular BLE devices through a GATT characteristic in the
Softdevice. The application is responsible for advertising and managing the external
connection, and the "BLE Gateway example" displays a way to achieve such behavior.

== Architecture details

link:docs/usage.adoc[Using the framework]

- A brief introduction to the Trickle mechanic, and overview of the API and the internal structure of the system.
- A brief introduction to the Trickle mechanic, and overview of the API and the
internal structure of the system.

link:../docs/how_it_works.adoc[How the mesh works]

- Detailed description of Trickle, the usage of the Softdevice (including GATT
characteristic syntax) and the on-air packets.

link:docs/how_it_works.adoc[How the mesh works]
== About
The "nRF OpenMesh" was created in collaboration with The Norwegian University of
Science and Technology (NTNU), as part of a master's thesis pre-study. The project is not
part of the official Nordic Semiconductor SDK. Developers are welcome to contribute
and provide feedback.

- Detailed description of Trickle, the usage of the Softdevice and the on-air packets.

== Forum
http://devzone.nordicsemi.com/[Nordic Developer Zone]

== Resources
http://www.nordicsemi.com[Nordic Semiconductor Homepage]
http://www.nordicsemi.com[Nordic Semiconductor Homepage]

http://tools.ietf.org/html/rfc6206[Trickle Algorithm Specification]

Expand Down
2 changes: 1 addition & 1 deletion application_controller/serial_interface/README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ All commands generate a Command Response Event with the status and the data asso
=== API

The API for the serial interface is present in
'mesh interface.h'
'rbc_mesh_interface.h'


== How it works
Expand Down
101 changes: 81 additions & 20 deletions application_controller/serial_interface/rbc_mesh_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,26 +59,43 @@ bool rbc_mesh_echo(uint8_t* buffer, int len){
bool rbc_mesh_init(
uint32_t accessAddr,
uint8_t chanNr,
uint8_t handleCount,
uint32_t advInt_ms){

if(chanNr != 37 && chanNr != 38 && chanNr != 39)
return false;
uint32_t int_min_ms){

hal_aci_data_t msg_for_mesh;
serial_cmd_t* p_cmd = (serial_cmd_t*) msg_for_mesh.buffer;

p_cmd->length = 11;
p_cmd->length = 10;
p_cmd->opcode = SERIAL_CMD_OPCODE_INIT;
p_cmd->params.init.access_addr = accessAddr;
p_cmd->params.init.channel = chanNr;
p_cmd->params.init.handle_count = handleCount;
p_cmd->params.init.adv_int_min = advInt_ms;
p_cmd->params.init.int_min = int_min_ms;

return hal_aci_tl_send(&msg_for_mesh);
}

bool rbc_mesh_value_set(uint8_t handle, uint8_t* buffer, int len){
bool rbc_mesh_start(void)
{
hal_aci_data_t msg_for_mesh;
serial_cmd_t* p_cmd = (serial_cmd_t*) msg_for_mesh.buffer;

p_cmd->length = 1;
p_cmd->opcode = SERIAL_CMD_OPCODE_START;

return hal_aci_tl_send(&msg_for_mesh);
}

bool rbc_mesh_stop(void)
{
hal_aci_data_t msg_for_mesh;
serial_cmd_t* p_cmd = (serial_cmd_t*) msg_for_mesh.buffer;

p_cmd->length = 1;
p_cmd->opcode = SERIAL_CMD_OPCODE_STOP;

return hal_aci_tl_send(&msg_for_mesh);
}

bool rbc_mesh_value_set(uint16_t handle, uint8_t* buffer, int len){

if (len > HAL_ACI_MAX_LENGTH - 1 || len < 1)
return false;
Expand All @@ -95,7 +112,7 @@ bool rbc_mesh_value_set(uint8_t handle, uint8_t* buffer, int len){
}


bool rbc_mesh_value_enable(uint8_t handle){
bool rbc_mesh_value_enable(uint16_t handle){

hal_aci_data_t msg_for_mesh;
serial_cmd_t* p_cmd = (serial_cmd_t*) msg_for_mesh.buffer;
Expand All @@ -107,7 +124,7 @@ bool rbc_mesh_value_enable(uint8_t handle){
return hal_aci_tl_send(&msg_for_mesh);
}

bool rbc_mesh_value_disable(uint8_t handle){
bool rbc_mesh_value_disable(uint16_t handle){

hal_aci_data_t msg_for_mesh;
serial_cmd_t* p_cmd = (serial_cmd_t*) msg_for_mesh.buffer;
Expand All @@ -119,7 +136,7 @@ bool rbc_mesh_value_disable(uint8_t handle){
return hal_aci_tl_send(&msg_for_mesh);
}

bool rbc_mesh_value_get(uint8_t handle){
bool rbc_mesh_value_get(uint16_t handle){

hal_aci_data_t msg_for_mesh;
serial_cmd_t* p_cmd = (serial_cmd_t*) msg_for_mesh.buffer;
Expand Down Expand Up @@ -166,26 +183,65 @@ bool rbc_mesh_channel_get(){
return hal_aci_tl_send(&msg_for_mesh);
}

bool rbc_mesh_handle_count_get(){
bool rbc_mesh_interval_min_get(){

hal_aci_data_t msg_for_mesh;
serial_cmd_t* p_cmd = (serial_cmd_t*) msg_for_mesh.buffer;

p_cmd->length = 1;
p_cmd->opcode = SERIAL_CMD_OPCODE_HANDLE_COUNT_GET;
p_cmd->opcode = SERIAL_CMD_OPCODE_INTERVAL_GET;
return hal_aci_tl_send(&msg_for_mesh);
}

bool rbc_mesh_adv_int_get(){
bool rbc_mesh_tx_event_flag_set(uint16_t handle, bool value)
{
hal_aci_data_t msg_for_mesh;
serial_cmd_t* p_cmd = (serial_cmd_t*) msg_for_mesh.buffer;
p_cmd->length = 5;
p_cmd->opcode = SERIAL_CMD_OPCODE_FLAG_SET;
p_cmd->params.flag_set.handle = handle;
p_cmd->params.flag_set.flag = ACI_FLAG_TX_EVENT;
p_cmd->params.flag_set.value = value;

return hal_aci_tl_send(&msg_for_mesh);
}

bool rbc_mesh_persistent_flag_set(uint16_t handle, bool value)
{
hal_aci_data_t msg_for_mesh;
serial_cmd_t* p_cmd = (serial_cmd_t*) msg_for_mesh.buffer;
p_cmd->length = 5;
p_cmd->opcode = SERIAL_CMD_OPCODE_FLAG_SET;
p_cmd->params.flag_set.handle = handle;
p_cmd->params.flag_set.flag = ACI_FLAG_PERSISTENT;
p_cmd->params.flag_set.value = value;

p_cmd->length = 1;
p_cmd->opcode = SERIAL_CMD_OPCODE_ADV_INT_GET;

return hal_aci_tl_send(&msg_for_mesh);
return hal_aci_tl_send(&msg_for_mesh);
}

bool rbc_mesh_tx_event_flag_get(uint16_t handle)
{
hal_aci_data_t msg_for_mesh;
serial_cmd_t* p_cmd = (serial_cmd_t*) msg_for_mesh.buffer;
p_cmd->length = 4;
p_cmd->opcode = SERIAL_CMD_OPCODE_FLAG_GET;
p_cmd->params.flag_get.handle = handle;
p_cmd->params.flag_get.flag = ACI_FLAG_TX_EVENT;

return hal_aci_tl_send(&msg_for_mesh);
}

bool rbc_mesh_persistent_flag_get(uint16_t handle)
{
hal_aci_data_t msg_for_mesh;
serial_cmd_t* p_cmd = (serial_cmd_t*) msg_for_mesh.buffer;
p_cmd->length = 4;
p_cmd->opcode = SERIAL_CMD_OPCODE_FLAG_GET;
p_cmd->params.flag_get.handle = handle;
p_cmd->params.flag_get.flag = ACI_FLAG_PERSISTENT;

return hal_aci_tl_send(&msg_for_mesh);
}

bool rbc_mesh_evt_get(serial_evt_t* p_evt){
Expand All @@ -202,3 +258,8 @@ void rbc_mesh_hw_init(aci_pins_t* pins){
hal_aci_tl_init(pins, false);
}

void rbc_mesh_radio_reset()
{
lib_aci_radio_reset();
}

Loading

0 comments on commit 6d2c36a

Please sign in to comment.