From 6d7141db0c73af34fd887fda9723c77aaaf1e349 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Fri, 29 May 2015 00:00:05 +0200 Subject: o Initial import of Phone Remote firmware, forked from the old soil moisture project. --- .gitignore | 5 + LiquidCrystal.c | 141 +++++++++++++++++++ LiquidCrystal.h | 19 +++ Makefile | 61 ++++++++ main.c | 429 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ phone_remote.c | 91 ++++++++++++ phone_remote.h | 9 ++ 7 files changed, 755 insertions(+) create mode 100644 .gitignore create mode 100644 LiquidCrystal.c create mode 100644 LiquidCrystal.h create mode 100644 Makefile create mode 100644 main.c create mode 100644 phone_remote.c create mode 100644 phone_remote.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dd4c77b --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +build +.project +.settings +.idea +.cproject diff --git a/LiquidCrystal.c b/LiquidCrystal.c new file mode 100644 index 0000000..becc07e --- /dev/null +++ b/LiquidCrystal.c @@ -0,0 +1,141 @@ +#include "LiquidCrystal.h" +#include "nrf_gpio.h" +#include "app_timer.h" + +/* + * Arduino | LCD | nrf51 + * D4 | DB4 | P0.16 + * D5 | DB5 | P0.17 + * D6 | DB6 | P0.18 + * D7 | DB7 | P0.10 + * D8 | RS | P0.20, register select. 0=instruction (write), 0=busy (read), 1=data + * D9 | EN | P0.23, clock, data is clocked in/out on falling edge + * D10 | DB4 | P0.24 + */ + +enum liquid_crystal_cmd { + LIQUID_CRYSTAL_CMD_CLEAR = 0x01, + LIQUID_CRYSTAL_CMD_RETURN_HOME = 0x02, + LIQUID_CRYSTAL_CMD_ENTRY_MODE_SET = 0x04, + LIQUID_CRYSTAL_CMD_DISPLAY = 0x08, + LIQUID_CRYSTAL_CMD_SHIFT = 0x10, + LIQUID_CRYSTAL_CMD_FUNCTION_SET = 0x20, + LIQUID_CRYSTAL_CMD_SET_CGRAM_ADDDRESS = 0x40, + LIQUID_CRYSTAL_CMD_SET_DDRAM_ADDDRESS = 0x80, +}; + +static struct { + uint8_t pin_db4; + uint8_t pin_db5; + uint8_t pin_db6; + uint8_t pin_db7; + uint8_t pin_rs; + uint8_t pin_en; + + app_gpiote_user_id_t gpio_user_id; +} data = { .pin_db4 = 16, .pin_db5 = 17, .pin_db6 = 18, .pin_db7 = 19, .pin_rs = + 20, .pin_en = 23, }; + +static uint32_t ticks_per_ms; + +static void event_handler() { +} + +static void wait_ms(uint32_t ms) { + uint32_t ticks; + + app_timer_cnt_get(&ticks); + + const uint32_t end_ticks = ticks + ms * ticks_per_ms; + + do { + app_timer_cnt_get(&ticks); + } while (ticks < end_ticks); +} + +static void write_4(uint8_t value) { + nrf_gpio_pin_write(data.pin_db4, value & 0x01); + nrf_gpio_pin_write(data.pin_db5, value & 0x02); + nrf_gpio_pin_write(data.pin_db6, value & 0x04); + nrf_gpio_pin_write(data.pin_db7, value & 0x08); + + nrf_gpio_pin_set(data.pin_en); + nrf_gpio_pin_clear(data.pin_en); +} + +static void write_value(uint8_t value, bool is_data) { + nrf_gpio_pin_write(data.pin_rs, is_data); + + write_4(value >> 4); + write_4(value); +} + +static void begin() { + nrf_gpio_pin_clear(data.pin_rs); + nrf_gpio_pin_clear(data.pin_en); + + // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION! + // according to datasheet, we need at least 40ms after power rises above 2.7V + // before sending commands. Arduino can turn on way before 4.5V so we'll wait 50 + wait_ms(50); + + write_4(0x03); + wait_ms(5); // 4.5ms + + write_4(0x03); + wait_ms(5); // 4.5ms + + write_4(0x03); + wait_ms(5); // 4.5ms + + write_4(0x02); + + write_value(LIQUID_CRYSTAL_CMD_DISPLAY, false); + +// _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; + liquid_crystal_display(true, true, true); +} + +void liquid_crystal_write_char(char chr) { + write_value(chr, true); +} + +void liquid_crystal_write_string(char *chr) { + while (*chr != '\0') { + liquid_crystal_write_char(*chr); + } +} + +uint32_t liquid_crystal_display(bool display_on, bool cursor_on, bool blink) { + uint8_t value = LIQUID_CRYSTAL_CMD_DISPLAY; + + value |= display_on ? 0x04 : 0x00; + value |= cursor_on ? 0x02 : 0x00; + value |= blink ? 0x01 : 0x00; + + write_value(value, false); + + return NRF_SUCCESS; +} + +uint32_t liquid_crystal_init(uint32_t _ticks_per_ms) { + ticks_per_ms = _ticks_per_ms; + + uint32_t err_code = app_gpiote_user_register(&data.gpio_user_id, 0x0000, + 0x0000, event_handler); + + if (err_code != NRF_SUCCESS) { + return err_code; + } + + nrf_gpio_cfg_output(data.pin_db4); + nrf_gpio_cfg_output(data.pin_db5); + nrf_gpio_cfg_output(data.pin_db6); + nrf_gpio_cfg_output(data.pin_db7); + nrf_gpio_cfg_output(data.pin_rs); + nrf_gpio_cfg_output(data.pin_en); + + begin(data); + + return NRF_SUCCESS; +} diff --git a/LiquidCrystal.h b/LiquidCrystal.h new file mode 100644 index 0000000..341d729 --- /dev/null +++ b/LiquidCrystal.h @@ -0,0 +1,19 @@ +/* + * LiquidCrystal + */ + +#ifndef LIQUIDCRYSTAL_H_ +#define LIQUIDCRYSTAL_H_ + +#include +#include "app_gpiote.h" + +uint32_t liquid_crystal_init(); + +uint32_t liquid_crystal_display(bool display_on, bool cursor_on, bool blink); + +void liquid_crystal_write_char(char chr); + +void liquid_crystal_write_string(char *chr); + +#endif diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..47155d4 --- /dev/null +++ b/Makefile @@ -0,0 +1,61 @@ +FLASHER ?= jlink +BOARD := BOARD_PCA10028 + +#TARGET_CHIP := NRF51822_QFAA_CA +#TARGET_CHIP := NRF51422_QFAC_AB +# nrf51442 - qfac +#DEVICE_VARIANT := xxac +USE_SOFTDEVICE = S110 + +ifeq ($(BOARD),BOARD_PCA10028) +TARGET_CHIP := NRF51422_QFAC_AB +DEVICE_VARIANT := xxac +else ifeq ($(BOARD),BOARD_PCA10031) +TARGET_CHIP := NRF51422_QFAC_AB +DEVICE_VARIANT := xxac +endif + +CFLAGS += -DBLE_STACK_SUPPORT_REQD +CFLAGS += -DSOFTDEVICE_PRESENT + +CFLAGS += -D$(USE_SOFTDEVICE) + +debug: CFLAGS += -DSM_DEBUG +debug: CFLAGS += -DENABLE_DEBUG_LOG_SUPPORT +debug: CFLAGS += -DDM_DISABLE_LOGS + +C_SOURCE_FILES += main.c +C_SOURCE_FILES += phone_remote.c +C_SOURCE_FILES += LiquidCrystal.c + +C_SOURCE_FILES += nrf_assert.c +C_SOURCE_FILES += nrf_delay.c +C_SOURCE_FILES += retarget.c +C_SOURCE_FILES += ble_sensorsim.c +C_SOURCE_FILES += bsp.c +C_SOURCE_FILES += app_button.c +C_SOURCE_FILES += app_error.c +C_SOURCE_FILES += app_timer.c +C_SOURCE_FILES += app_gpiote.c +#C_SOURCE_FILES += app_scheduler.c +C_SOURCE_FILES += app_trace.c +C_SOURCE_FILES += app_fifo.c +C_SOURCE_FILES += app_uart_fifo.c +C_SOURCE_FILES += pstorage.c +#C_SOURCE_FILES += ble_hrs.c +#C_SOURCE_FILES += ble_dis.c +#C_SOURCE_FILES += ble_bas.c +C_SOURCE_FILES += ble_conn_params.c +C_SOURCE_FILES += ble_advdata.c +C_SOURCE_FILES += ble_srv_common.c +C_SOURCE_FILES += device_manager_peripheral.c +C_SOURCE_FILES += softdevice_handler.c + +PROJECT_NAME := phone_remote_nrf51 +SDK_SOURCE_PATH = $(SDK_PATH)/components +SOFTDEVICE_HEX_PATH = $(HOME)/opt/nrf-sdk/s110/s110_nrf51822_7.1.0_softdevice.hex + +all: debug + +include ~/.nrf51822-posix-build-scripts.mk +include $(TEMPLATE_PATH)/Makefile.common diff --git a/main.c b/main.c new file mode 100644 index 0000000..34b8ae4 --- /dev/null +++ b/main.c @@ -0,0 +1,429 @@ +/* Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. + * + */ +/** @example examples/ble_peripheral/ble_app_hrs/main.c + * + * @brief Heart Rate Service Sample Application main file. + * + * This file contains the source code for a sample application using the Heart Rate service + * (and also Battery and Device Information services). This application uses the + * @ref srvlib_conn_params module. + */ + +#include +#include +#include "nordic_common.h" +#include "nrf.h" +#include "app_error.h" +#include "nrf51_bitfields.h" +#include "ble.h" +#include "ble_hci.h" +#include "ble_srv_common.h" +#include "ble_advdata.h" +#include "ble_gatt.h" +#include "ble_bas.h" +#include "ble_hrs.h" +#include "ble_dis.h" +#ifdef BLE_DFU_APP_SUPPORT +#include "ble_dfu.h" +#include "dfu_app_handler.h" +#endif // BLE_DFU_APP_SUPPORT +#include "ble_conn_params.h" +#include "boards.h" +#include "ble_sensorsim.h" +#include "softdevice_handler.h" +#include "app_timer.h" +#include "device_manager.h" +#include "pstorage.h" +#include "app_trace.h" +#include "app_timer.h" +#include "app_gpiote.h" +#include "app_timer.h" +#include "bsp.h" + +#include "phone_remote.h" +#include "LiquidCrystal.h" + +#include + +#define dbg printf + +#define IS_SRVC_CHANGED_CHARACT_PRESENT 0 /**< Include or not the service_changed characteristic. if not enabled, the server's database cannot be changed for the lifetime of the device*/ + +// BOARD_PCA10031 doesn't have any buttons according to the BSP +#ifndef BOARD_PCA10031 +#define WAKEUP_BUTTON_ID 0 /**< Button used to wake up the application. */ +#define BOND_DELETE_ALL_BUTTON_ID 1 /**< Button used for deleting all bonded centrals during startup. */ +#endif + +#define DEVICE_NAME "Woot-51" +#define MANUFACTURER_NAME "NordicSemiconductor" +#define APP_ADV_INTERVAL 40 /**< The advertising interval (in units of 0.625 ms. This value corresponds to 25 ms). */ +#define APP_ADV_TIMEOUT_IN_SECONDS 180 /**< The advertising timeout in units of seconds. */ + +#define APP_TIMER_PRESCALER 0 /**< Value of the RTC1 PRESCALER register. */ +#define APP_TIMER_MAX_TIMERS (6+BSP_APP_TIMERS_NUMBER) /**< Maximum number of simultaneously created timers. */ +#define APP_TIMER_OP_QUEUE_SIZE 4 /**< Size of timer operation queues. */ + +#define SENSOR_CONTACT_DETECTED_INTERVAL APP_TIMER_TICKS(5000, APP_TIMER_PRESCALER) /**< Sensor Contact Detected toggle interval (ticks). */ + +#define MIN_CONN_INTERVAL MSEC_TO_UNITS(500, UNIT_1_25_MS) /**< Minimum acceptable connection interval (0.5 seconds). */ +#define MAX_CONN_INTERVAL MSEC_TO_UNITS(1000, UNIT_1_25_MS) /**< Maximum acceptable connection interval (1 second). */ +#define SLAVE_LATENCY 0 /**< Slave latency. */ +#define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) /**< Connection supervisory timeout (4 seconds). */ + +#define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000, APP_TIMER_PRESCALER) /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */ +#define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000, APP_TIMER_PRESCALER)/**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */ +#define MAX_CONN_PARAMS_UPDATE_COUNT 3 /**< Number of attempts before giving up the connection parameter negotiation. */ + +#define SEC_PARAM_TIMEOUT 30 /**< Timeout for Pairing Request or Security Request (in seconds). */ +#define SEC_PARAM_BOND 1 /**< Perform bonding. */ +#define SEC_PARAM_MITM 0 /**< Man In The Middle protection not required. */ +#define SEC_PARAM_IO_CAPABILITIES BLE_GAP_IO_CAPS_NONE /**< No I/O capabilities. */ +#define SEC_PARAM_OOB 0 /**< Out Of Band data not available. */ +#define SEC_PARAM_MIN_KEY_SIZE 7 /**< Minimum encryption key size. */ +#define SEC_PARAM_MAX_KEY_SIZE 16 /**< Maximum encryption key size. */ + +#define DEAD_BEEF 0xDEADBEEF /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */ + +static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< Handle of the current connection. */ +static ble_gap_adv_params_t m_adv_params; /**< Parameters to be passed to the stack when starting advertising. */ + +static dm_application_instance_t m_app_handle; /**< Application identifier allocated by device manager */ + +static bool m_memory_access_in_progress = false; /**< Flag to keep track of ongoing operations on persistent memory. */ + + +static app_timer_id_t hello_timer; + +void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name) +{ + app_error_handler(DEAD_BEEF, line_num, p_file_name); +} + +static uint32_t seconds = 0; + +static void hello_timer_handler(void* data) +{ + uint32_t ticks; + app_timer_cnt_get(&ticks); + + uint32_t ms = (1000 * (1 + APP_TIMER_PRESCALER) * ticks) / APP_TIMER_CLOCK_FREQ; + + seconds++; + printf("hello world, seconds=%" PRIu32 ", ticks=%" PRIu32 ", ms=%" PRIu32 "\r\n", seconds, ticks, ms); +} + +static void timers_init(void) +{ + uint32_t err_code; + + // Initialize timer module. + APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_MAX_TIMERS, APP_TIMER_OP_QUEUE_SIZE, false); + + err_code = app_timer_create(&hello_timer, APP_TIMER_MODE_REPEATED, hello_timer_handler); + APP_ERROR_CHECK(err_code); +} + +static void timers_start() { + uint32_t err_code; + + uint32_t ticks = APP_TIMER_TICKS(1000, APP_TIMER_PRESCALER); + err_code = app_timer_start(hello_timer, ticks, NULL); + APP_ERROR_CHECK(err_code); +} + +static void gap_params_init(void) +{ + uint32_t err_code; + ble_gap_conn_params_t gap_conn_params; + ble_gap_conn_sec_mode_t sec_mode; + + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); + + err_code = sd_ble_gap_device_name_set(&sec_mode, + (const uint8_t *)DEVICE_NAME, + strlen(DEVICE_NAME)); + APP_ERROR_CHECK(err_code); + + err_code = sd_ble_gap_appearance_set(BLE_APPEARANCE_HEART_RATE_SENSOR_HEART_RATE_BELT); + APP_ERROR_CHECK(err_code); + + memset(&gap_conn_params, 0, sizeof(gap_conn_params)); + + gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL; + gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL; + gap_conn_params.slave_latency = SLAVE_LATENCY; + gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT; + + err_code = sd_ble_gap_ppcp_set(&gap_conn_params); + APP_ERROR_CHECK(err_code); +} + + +static void advertising_init(void) +{ + uint32_t err_code; + ble_advdata_t advdata; + uint8_t flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; + + ble_uuid_t adv_uuids[] = {}; + + // Build and set advertising data. + memset(&advdata, 0, sizeof(advdata)); + + advdata.name_type = BLE_ADVDATA_FULL_NAME; + advdata.include_appearance = true; + advdata.flags.size = sizeof(flags); + advdata.flags.p_data = &flags; + advdata.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]); + advdata.uuids_complete.p_uuids = adv_uuids; + + err_code = ble_advdata_set(&advdata, NULL); + APP_ERROR_CHECK(err_code); + + // Initialize advertising parameters (used when starting advertising). + memset(&m_adv_params, 0, sizeof(m_adv_params)); + + m_adv_params.type = BLE_GAP_ADV_TYPE_ADV_IND; + m_adv_params.p_peer_addr = NULL; // Undirected advertisement. + m_adv_params.fp = BLE_GAP_ADV_FP_ANY; + m_adv_params.interval = APP_ADV_INTERVAL; + m_adv_params.timeout = APP_ADV_TIMEOUT_IN_SECONDS; +} + +/**@brief Function for initializing services that will be used by the application. + * + * @details Initialize the Heart Rate, Battery and Device Information services. + */ +static void services_init(void) +{ + uint32_t err_code = NRF_SUCCESS; + +// err_code = sm_add_services(); + APP_ERROR_CHECK(err_code); +} + +static void advertising_start(void) +{ + uint32_t err_code; + uint32_t count; + + // Verify if there is any flash access pending, if yes delay starting advertising until + // it's complete. + err_code = pstorage_access_status_get(&count); + APP_ERROR_CHECK(err_code); + + if (count != 0) + { + m_memory_access_in_progress = true; + return; + } + + err_code = sd_ble_gap_adv_start(&m_adv_params); + APP_ERROR_CHECK(err_code); + + err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING); + APP_ERROR_CHECK(err_code); +} + +static void on_conn_params_evt(ble_conn_params_evt_t * p_evt) +{ + uint32_t err_code; + + if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED) + { + err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE); + APP_ERROR_CHECK(err_code); + } +} + +static void conn_params_error_handler(uint32_t nrf_error) +{ + APP_ERROR_HANDLER(nrf_error); +} + +static void conn_params_init(void) +{ + uint32_t err_code; + ble_conn_params_init_t cp_init; + + memset(&cp_init, 0, sizeof(cp_init)); + + cp_init.p_conn_params = NULL; + cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY; + cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY; + cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT; + cp_init.disconnect_on_fail = false; + cp_init.evt_handler = on_conn_params_evt; + cp_init.error_handler = conn_params_error_handler; + + err_code = ble_conn_params_init(&cp_init); + APP_ERROR_CHECK(err_code); +} + +static void on_ble_evt(ble_evt_t * p_ble_evt) +{ + uint32_t err_code; + + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_CONNECTED: + + err_code = bsp_indication_set(BSP_INDICATE_CONNECTED); + APP_ERROR_CHECK(err_code); + m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; + break; + + case BLE_GAP_EVT_DISCONNECTED: + err_code = bsp_indication_set(BSP_INDICATE_IDLE); + APP_ERROR_CHECK(err_code); + advertising_start(); + break; + + case BLE_GAP_EVT_TIMEOUT: + + if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISEMENT) + { + printf("re-starting advertisement"); + advertising_start(); + /* + err_code = bsp_indication_set(BSP_INDICATE_IDLE); + APP_ERROR_CHECK(err_code); + + // Go to system-off mode (this function will not return; wakeup will cause a reset). + err_code = sd_power_system_off(); + APP_ERROR_CHECK(err_code); + */ + } + break; + + default: + // No implementation needed. + break; + } +} + +static void ble_evt_dispatch(ble_evt_t * p_ble_evt) +{ +// sm_on_ble_evt(p_ble_evt); + + dm_ble_evt_handler(p_ble_evt); + on_ble_evt(p_ble_evt); +} + +static void sys_evt_dispatch(uint32_t sys_evt) +{ + pstorage_sys_event_handler(sys_evt); +} + +static void ble_stack_init(void) +{ + uint32_t err_code; + + // Initialize the SoftDevice handler module. + SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, false); + + ble_enable_params_t ble_enable_params; + memset(&ble_enable_params, 0, sizeof(ble_enable_params)); + ble_enable_params.gatts_enable_params.service_changed = IS_SRVC_CHANGED_CHARACT_PRESENT; + err_code = sd_ble_enable(&ble_enable_params); + APP_ERROR_CHECK(err_code); + + err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch); + APP_ERROR_CHECK(err_code); + + err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch); + APP_ERROR_CHECK(err_code); +} + +static uint32_t device_manager_evt_handler(dm_handle_t const * p_handle, + dm_event_t const * p_event, + api_result_t event_result) +{ + APP_ERROR_CHECK(event_result); + + switch(p_event->event_id) + { + } + + return NRF_SUCCESS; +} + +static void device_manager_init(void) +{ + uint32_t err_code; + dm_init_param_t init_data; + dm_application_param_t register_param; + + // Initialize persistent storage module. + err_code = pstorage_init(); + APP_ERROR_CHECK(err_code); + + init_data.clear_persistent_data = false; // was true + + err_code = dm_init(&init_data); + APP_ERROR_CHECK(err_code); + + memset(®ister_param.sec_param, 0, sizeof(ble_gap_sec_params_t)); + + register_param.sec_param.timeout = SEC_PARAM_TIMEOUT; + register_param.sec_param.bond = SEC_PARAM_BOND; + register_param.sec_param.mitm = SEC_PARAM_MITM; + register_param.sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES; + register_param.sec_param.oob = SEC_PARAM_OOB; + register_param.sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE; + register_param.sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE; + register_param.evt_handler = device_manager_evt_handler; + register_param.service_type = DM_PROTOCOL_CNTXT_GATT_SRVR_ID; + + err_code = dm_register(&m_app_handle, ®ister_param); + APP_ERROR_CHECK(err_code); +} + +static void power_manage(void) +{ + uint32_t err_code = sd_app_evt_wait(); + APP_ERROR_CHECK(err_code); +} + +int main(void) +{ + app_trace_init(); + + dbg("Soil Moisture device starting...\r\n"); + + ble_stack_init(); + timers_init(); + + APP_GPIOTE_INIT(2); + + uint32_t err_code = bsp_init(BSP_INIT_LED | BSP_INIT_BUTTONS, APP_TIMER_TICKS(100, APP_TIMER_PRESCALER), NULL); + APP_ERROR_CHECK(err_code); + +// device_manager_init(); +// gap_params_init(); +// advertising_init(); +// services_init(); +// conn_params_init(); + + timers_start(); + + liquid_crystal_init(APP_TIMER_TICKS(1, APP_TIMER_PRESCALER)); + liquid_crystal_write_string("hello world!"); + + advertising_start(); + + for (;; ) + { + power_manage(); + } +} diff --git a/phone_remote.c b/phone_remote.c new file mode 100644 index 0000000..c37123a --- /dev/null +++ b/phone_remote.c @@ -0,0 +1,91 @@ +#include "phone_remote.h" +#include "ble.h" +#include "nrf_error.h" +#include "nrf_gpio.h" + +#include +#include +#include + +// 32D0xxxx-035D-59C5-70D3-BC8E4A1FD83F +#define TRYGVIS_IO_UUID_BASE {0x3f, 0xd8, 0x1f, 0x4a, 0x8e, 0xbc, 0xd3, 0x70, 0xc5, 0x59, 0x5d, 0x03, 0, 0, 0xd0, 0x32} + +#define TRYGVIS_IO_UUID_SERVICE_PHONE_REMOTE 0x0020 +#define TRYGVIS_IO_UUID_CHARACTERISTIC_PHONE_REMOTE_BUTTON 0x0021 + +static uint8_t trygvis_io_uuid_type; +static uint16_t pr_service_handle; +static ble_gatts_char_handles_t pr_char_handle; + +static uint16_t conn_handle = BLE_CONN_HANDLE_INVALID; + +// The value of the soil moisture control characteristic. +static uint8_t control_value[100] = {1, 2, 3}; + +#define dbg printf + +uint32_t pr_add_services() { + uint32_t err_code; + + dbg("pr: pr_add_services\r\n"); + + ble_uuid128_t base_uuid = {TRYGVIS_IO_UUID_BASE}; + err_code = sd_ble_uuid_vs_add(&base_uuid, &trygvis_io_uuid_type); + if (err_code != NRF_SUCCESS) { + return err_code; + } + + // ------------------------------------------------------------------------- + // Service + // ------------------------------------------------------------------------- + + ble_uuid_t ble_uuid_svc = { + .type = trygvis_io_uuid_type, + .uuid = TRYGVIS_IO_UUID_SERVICE_PHONE_REMOTE + }; + + err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid_svc, &pr_service_handle); + if (err_code != NRF_SUCCESS) { + return err_code; + } + + // ------------------------------------------------------------------------- + // Characteristic + // ------------------------------------------------------------------------- + + ble_gatts_char_md_t char_md; + + memset(&char_md, 0, sizeof(char_md)); + + char_md.char_props.read = 1; + char_md.char_props.write = 1; + char_md.char_props.notify = 1; + + ble_uuid_t ble_uuid_chr = { + .type = trygvis_io_uuid_type, + .uuid = TRYGVIS_IO_UUID_CHARACTERISTIC_PHONE_REMOTE_BUTTON + }; + + ble_gatts_attr_md_t attr_md; + memset(&attr_md, 0, sizeof(attr_md)); + + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm); + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); + attr_md.vlen = 1; + attr_md.vloc = BLE_GATTS_VLOC_USER; + + ble_gatts_attr_t attr_char_value; + memset(&attr_char_value, 0, sizeof(attr_char_value)); + + attr_char_value.p_uuid = &ble_uuid_chr; + attr_char_value.p_attr_md = &attr_md; + attr_char_value.init_len = 3; + attr_char_value.init_offs = 0; + attr_char_value.max_len = sizeof(control_value); + attr_char_value.p_value = control_value; + + return sd_ble_gatts_characteristic_add(pr_service_handle, + &char_md, + &attr_char_value, + &pr_char_handle); +} diff --git a/phone_remote.h b/phone_remote.h new file mode 100644 index 0000000..6437cbc --- /dev/null +++ b/phone_remote.h @@ -0,0 +1,9 @@ +#ifndef PHONE_REMOTE_H_ +#define PHONE_REMOTE_H_ + +#include "ble.h" + +uint32_t pr_add_services(); +void pr_on_ble_evt(ble_evt_t* ble_evt); + +#endif -- cgit v1.2.3