Skip to content

Commit

Permalink
Time sync working
Browse files Browse the repository at this point in the history
  • Loading branch information
ps2 committed Apr 21, 2017
1 parent 285fa14 commit 81fde7b
Show file tree
Hide file tree
Showing 10 changed files with 238 additions and 117 deletions.
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ RBC_MESH := rbc_mesh
LINKER_SCRIPT := $(SIMBLEE_BASE)/variants/Simblee/linker_scripts/gcc/Simblee.ld
RFD_LOADER := $(SIMBLEE_BASE)/RFDLoader_osx
#SERIAL_PORT := /dev/cu.usbserial-DN00D34P # left
#SERIAL_PORT := /dev/cu.usbserial-DN00CSZ7 # right
SERIAL_PORT := /dev/cu.usbserial-DN00CSZ7 # right
#SERIAL_PORT := /dev/cu.usbserial-A105RB12
#SERIAL_PORT := /dev/cu.usbserial-FTZ86FTC
SERIAL_PORT := /dev/cu.usbserial-DO00C2G2
#SERIAL_PORT := /dev/cu.usbserial-DO00C2G2

ifeq ($(USE_RBC_MESH_SERIAL), "yes")
SERIAL_STRING := "_serial"
Expand Down Expand Up @@ -93,7 +93,7 @@ remduplicates = $(strip $(if $1,$(firstword $1) $(call remduplicates,$(filter-ou

# source common to all targets

C_SOURCE_FILES += src/main.c src/leds.c src/config.c src/sensor.c src/app_cmd.c src/time_sync.c src/proximity.c src/heartbeat.c
C_SOURCE_FILES += src/main.c src/leds.c src/config.c src/sensor.c src/app_cmd.c src/scheduler.c src/proximity.c src/heartbeat.c
C_SOURCE_FILES += $(COMPONENTS)/libraries/timer/app_timer.c

CXX_SOURCE_FILES += $(SIMBLEE_BASE)/libraries/SimbleeBLE/SimbleeBLE.cpp
Expand Down
2 changes: 1 addition & 1 deletion pyaci/aci/AciEvent.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def __init__(self,pkt):
if self.Len < 3:
logging.error("Invalid length for %s event: %s", self.__class__.__name__, str(pkt))
else:
self.ValueHandle = (pkt[2] << 8) + pkt[3]
self.ValueHandle = (pkt[3] << 8) + pkt[2]
self.Data = pkt[4:]

def __repr__(self):
Expand Down
13 changes: 7 additions & 6 deletions src/heartbeat.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
#include "mesh_packet.h"
#include "transport_control.h"
#include "config.h"
#include "time_sync.h"
#include "leds.h"
#include "scheduler.h"

static tc_tx_config_t m_tx_config;

Expand All @@ -14,7 +14,7 @@ void heartbeat_init() {
m_tx_config.tx_power = RBC_MESH_TXPOWER_0dBm;
}

void send_heartbeat_packet() {
void send_heartbeat_packet(uint8_t sensor_id, uint32_t epoch_seconds, uint16_t epoch_ms, uint16_t clock_version) {
// Send out time sync packet

mesh_packet_t *p_packet;
Expand All @@ -34,9 +34,10 @@ void send_heartbeat_packet() {
p_adv_data->adv_data_type = HEARTBEAT_ADV_DATA_TYPE; // Normal mesh packets are MESH_ADV_DATA_TYPE (0x16)

heartbeat_ad_t* p_heartbeat_ad = (heartbeat_ad_t*) &p_adv_data->data[0];
p_heartbeat_ad->sensor_id = get_sensor_id();
p_heartbeat_ad->epoch_time = get_clock_time();
p_heartbeat_ad->clock_version = get_clock_version();
p_heartbeat_ad->sensor_id = sensor_id;
p_heartbeat_ad->epoch_seconds = epoch_seconds;
p_heartbeat_ad->epoch_ms = epoch_ms;
p_heartbeat_ad->clock_version = clock_version;

if (tc_tx(p_packet, &m_tx_config) != NRF_SUCCESS) {
toggle_led(LED_RED);
Expand All @@ -47,5 +48,5 @@ void send_heartbeat_packet() {
}

void received_heartbeat(heartbeat_ad_t *p_heartbeat_ad) {
set_clock_time(p_heartbeat_ad->epoch_time, 0, CLOCK_SOURCE_RF, p_heartbeat_ad->clock_version);
set_clock_time(p_heartbeat_ad->epoch_seconds, p_heartbeat_ad->epoch_ms, CLOCK_SOURCE_RF, p_heartbeat_ad->clock_version);
}
5 changes: 3 additions & 2 deletions src/heartbeat.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@
typedef __packed_armcc struct
{
uint8_t sensor_id;
uint32_t epoch_time;
uint32_t epoch_seconds;
uint16_t epoch_ms;
uint16_t clock_version;
} __packed_gcc heartbeat_ad_t;


void heartbeat_init();
void send_heartbeat_packet();
void send_heartbeat_packet(uint8_t sensor_id, uint32_t epoch_seconds, uint16_t current_ms, uint16_t clock_version);
void received_heartbeat(heartbeat_ad_t *p_heartbeat_ad);

#endif // HEARTBEAT_H
18 changes: 2 additions & 16 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include "config.h"
#include "sensor.h"
#include "transport_control.h"
#include "time_sync.h"
#include "scheduler.h"
#include "heartbeat.h"
#include <stdbool.h>
#include <stdint.h>
Expand Down Expand Up @@ -110,23 +110,10 @@ void clock_initialization()
static void packet_peek_cb(rbc_mesh_packet_peek_params_t *params) {
if (params->packet_type == BLE_PACKET_TYPE_ADV_NONCONN_IND &&
params->p_payload[1] == HEARTBEAT_ADV_DATA_TYPE) {
toggle_led(LED_BLUE);
received_heartbeat((heartbeat_ad_t*)&params->p_payload[2]);
}
}

// Main timer callbacks; from the synchronized clock
void main_timer_cb() {
if (get_clock_time() % 10 == 0) {
toggle_led(LED_GREEN);
send_heartbeat_packet();
}
}

void offset_timer_cb() {
sensor_update();
}

int main(void)
{
//clock_initialization();
Expand Down Expand Up @@ -174,7 +161,7 @@ int main(void)
tc_radio_params_set(MESH_ACCESS_ADDR, app_config.mesh_channel);
}

time_sync_init(); // Initializes, but does not start, timer
scheduler_init(); // Initializes, but does not start, timer
heartbeat_init(); // Inits structures for sending heartbeat

/* Initialize serial ACI */
Expand All @@ -190,7 +177,6 @@ int main(void)
/* Enable our handle */
if (app_config.sensor_id > 0) {
sensor_init();
toggle_led(LED_GREEN);
}

/* Main event loop */
Expand Down
204 changes: 204 additions & 0 deletions src/scheduler.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@

#include "scheduler.h"
#include "leds.h"
#include "sensor.h"
#include "app_timer.h"
#include "config.h"
#include "rand.h"
#include "heartbeat.h"
#include "sensor.h"
#include "rbc_mesh.h"

// Timer settings
#define APP_TIMER_PRESCALER 15 // divisor value - 1
#define TICKS_PER_SECOND 2048 // f / (APP_TIMER_PRESCALER+1)
#define TICKS_PER_100ms 205 // f / (APP_TIMER_PRESCALER+1) / 10
#define APP_TIMER_MAX_TIMERS 3
#define APP_TIMER_OP_QUEUE_SIZE 4

static int32_t m_current_time;
static int16_t m_clock_version = 0;
static app_timer_id_t m_clock_sync_timer_ID;
static app_timer_id_t m_offset_timer_ID;
static app_timer_id_t m_periodic_timer_ID;
static scheduler_state_t m_scheduler_state;
static prng_t m_rand;
static uint32_t m_clock_second_start_counter_value;

#define MS_TO_TICKS(MS) ((TICKS_PER_100ms * (MS)) / 100)
#define TICKS_TO_MS(TICKS) (100 * (TICKS) / TICKS_PER_100ms)

static void offset_timer_cb(void * p_context);
static void delay_to_heartbeat();

#define DEBUG_REGISTER_SIZE (16)
#define DEBUG_REGISTER_HANDLE (0x1234)
static uint8_t debug_counter;
static uint8_t debug_register[DEBUG_REGISTER_SIZE];

static void add_value_to_debug_register(uint8_t value) {
debug_register[debug_counter % DEBUG_REGISTER_SIZE] = value;
debug_counter++;
}
static void report_debug_register() {
rbc_mesh_value_set(DEBUG_REGISTER_HANDLE, debug_register, DEBUG_REGISTER_SIZE);
}

static void periodic_timer_cb(void * p_context)
{

led_config(LED_GREEN, 1);
app_timer_cnt_get(&m_clock_second_start_counter_value);
m_scheduler_state = SCHEDULER_STATE_BEFORE_HB;
m_current_time += 1;
//rbc_mesh_start();

if (m_current_time % 10 == 0) {
//report_debug_register();
}

// Delay to heartbeat
delay_to_heartbeat();
}

static void delay_to_heartbeat() {
uint16_t random_tx_delay = ((rand_prng_get(&m_rand) & 0x3ff) * HEARTBEAT_WINDOW_MS) / 0x3ff;
int32_t delay_ticks = MS_TO_TICKS(MAX_EXPECTED_CLOCK_SKEW_MS + random_tx_delay);
if (random_tx_delay > 1000) {
toggle_led(LED_RED);
}
add_value_to_debug_register(delay_ticks & 0xff);
delay_ticks = 5 + (debug_counter * 2) % 205;
if (delay_ticks > 5) {
if (app_timer_start(m_offset_timer_ID, delay_ticks, NULL) != NRF_SUCCESS) {
toggle_led(LED_RED);
}
} else {
toggle_led(LED_RED);
offset_timer_cb(NULL);
}
}

static void do_heartbeat() {
led_config(LED_BLUE, 1);
uint32_t current_counter;
app_timer_cnt_get(&current_counter);
// Modulo wraparound makes this ok
uint32_t elapsed_ticks_since_second_start = current_counter - m_clock_second_start_counter_value;
send_heartbeat_packet(get_sensor_id(), m_current_time, TICKS_TO_MS(elapsed_ticks_since_second_start), m_clock_version);
}

static void delay_to_reporting() {
// We do a fixed delay here, even though the last delay (delay_to_heartbeat)
// was a random interval, as we want the reporting to start with some randomness
// as well, to avoid all nodes starting the mesh sync at the same time
int32_t delay_ticks = MS_TO_TICKS(HEARTBEAT_WINDOW_MS);
if (delay_ticks > 5) {
app_timer_start(m_offset_timer_ID, delay_ticks, NULL);
} else {
offset_timer_cb(NULL);
}
}

static void do_reporting() {
led_config(LED_BLUE, 0);
report_sensor_data();
}

static void delay_to_sleep() {
uint32_t current_counter;
app_timer_cnt_get(&current_counter);
uint32_t elapsed_ticks_since_second_start = current_counter - m_clock_second_start_counter_value;
int32_t delay_ticks = MS_TO_TICKS(TOTAL_RADIO_WINDOW_MS) - elapsed_ticks_since_second_start;
if (delay_ticks > 5) {
app_timer_start(m_offset_timer_ID, delay_ticks, NULL);
} else {
offset_timer_cb(NULL);
}
}

static void do_sleep() {
//rbc_mesh_stop();
led_config(LED_GREEN, 0);
}

static void offset_timer_cb(void * p_context) {
app_timer_stop(m_offset_timer_ID);

switch (m_scheduler_state) {
case SCHEDULER_STATE_BEFORE_HB:
do_heartbeat();
m_scheduler_state = SCHEDULER_STATE_AFTER_HB;
delay_to_reporting();
break;
case SCHEDULER_STATE_AFTER_HB:
do_reporting();
m_scheduler_state = SCHEDULER_STATE_REPORTING;
delay_to_sleep();
break;
case SCHEDULER_STATE_REPORTING:
do_sleep();
m_scheduler_state = SCHEDULER_STATE_SLEEP;
// periodic timer will wake us next time
break;
default:
toggle_led(LED_RED);
break;
}
}

static void start_periodic_timer() {
app_timer_start(m_periodic_timer_ID, TICKS_PER_SECOND, NULL);
}

static void clock_sync_cb(void * p_context) {
m_current_time += 1;
start_periodic_timer();
}

static void start_timer(uint16_t start_delay) {
int32_t start_delay_ticks = (start_delay * (TICKS_PER_SECOND/1000.0));
if (start_delay_ticks > 5) {
app_timer_start(m_clock_sync_timer_ID, start_delay_ticks, NULL);
} else {
start_periodic_timer();
}
}

void scheduler_init() {
rand_prng_seed(&m_rand);
m_scheduler_state = SCHEDULER_STATE_STOPPED;
APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_MAX_TIMERS, APP_TIMER_OP_QUEUE_SIZE, false);
app_timer_create(&m_periodic_timer_ID, APP_TIMER_MODE_REPEATED, periodic_timer_cb);
app_timer_create(&m_clock_sync_timer_ID, APP_TIMER_MODE_SINGLE_SHOT, clock_sync_cb);
app_timer_create(&m_offset_timer_ID, APP_TIMER_MODE_SINGLE_SHOT, offset_timer_cb);
}

void set_clock_time(int32_t epoch, uint16_t ms, clock_source_t clock_source, int16_t clock_version) {

if (clock_source == CLOCK_SOURCE_RF) {
// modulo math to handle wraparound
uint16_t version_delta = clock_version - m_clock_version;
if (version_delta > 0 && version_delta < 0xff00) {
m_clock_version = clock_version;
} else {
// Older or same clock version
return;
}
} else if (clock_source == CLOCK_SOURCE_SERIAL) {
m_clock_version++;
}
m_current_time = epoch;
uint16_t start_delay = (1000 - ms) % 1000;
app_timer_stop(m_periodic_timer_ID);
app_timer_stop(m_clock_sync_timer_ID);
start_timer(start_delay);
}

int32_t get_clock_time() {
return m_current_time;
}

int16_t get_clock_version() {
return m_clock_version;
}
24 changes: 16 additions & 8 deletions src/time_sync.h → src/scheduler.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#ifndef __TIME_SYNC_H_
#define __TIME_SYNC_H_
#ifndef __SCHEDULER_H_
#define __SCHEDULER_H_

#include <stdint.h>
#include "toolchain.h"
Expand All @@ -10,7 +10,19 @@ typedef enum {
CLOCK_SOURCE_SERIAL,
} clock_source_t;

void time_sync_init();
typedef enum {
SCHEDULER_STATE_STOPPED,
SCHEDULER_STATE_SLEEP,
SCHEDULER_STATE_BEFORE_HB,
SCHEDULER_STATE_AFTER_HB,
SCHEDULER_STATE_REPORTING,
} scheduler_state_t;

#define MAX_EXPECTED_CLOCK_SKEW_MS (10)
#define HEARTBEAT_WINDOW_MS (100)
#define TOTAL_RADIO_WINDOW_MS (400)

void scheduler_init();
void set_clock_time(int32_t epoch, uint16_t ms, clock_source_t clock_source, int16_t clock_version);

// Returns unix epoch
Expand All @@ -19,8 +31,4 @@ int32_t get_clock_time();
// in the heartbeat message
int16_t get_clock_version();

// Callbacks
void main_timer_cb();
void offset_timer_cb();

#endif //__TIME_SYNC_H_
#endif //__SCHEDULER_H_
2 changes: 1 addition & 1 deletion src/sensor.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ void sensor_init() {
APP_ERROR_CHECK(error_code);
}

void sensor_update() {
void report_sensor_data() {
uint32_t error_code;
error_code = rbc_mesh_value_set(SENSOR_HANDLE, (uint8_t*)&m_value, sizeof(sensor_value_t));
APP_ERROR_CHECK(error_code);
Expand Down
2 changes: 1 addition & 1 deletion src/sensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ typedef __packed_armcc struct

void sensor_init();

void sensor_update();
void report_sensor_data();

#endif
Loading

0 comments on commit 81fde7b

Please sign in to comment.