Run on TY51822r3 board with ACC sensor (LIS3DH or BMC050)

Dependencies:   BLE_API LIS3DH mbed nRF51822 BMC050 nRF51_LowPwr nRF51_Vdd

Fork of BLE_EddystoneBeacon_Service by Bluetooth Low Energy

main.cpp

Committer:
kenjiArai
Date:
2016-06-11
Revision:
37:ea459e6c6a35
Parent:
36:5508506dda71

File content as of revision 37:ea459e6c6a35:

/* mbed Microcontroller Library
 * Copyright (c) 2006-2013 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 *  /////// Works well on Switch Science mbed TY51822r3 ///////
 *  Modified by Kenji Arai
 *      http://www.page.sannet.ne.jp/kenjia/index.html
 *      http://mbed.org/users/kenjiArai/
 *
 *      Started:  Feburary  1st, 2016
 *      Revised:  June      8th, 2016
 *
 *  Original:
 *      nRF51822_SimpleControls
 *      https://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_EddystoneBeacon_Service/
 *  Tested Controller Device:
 *      iPhone6 Physical Web (PhyWeb) By Viet Hoa Dinh
 *      https://itunes.apple.com/us/app/physical-web/id927653608?mt=8
 */

/*
 *  STEP1
 *      If you just got the board, plese set following difinition and not connect all of pins.
#define USE_ACC                 0
#define CHK_ACC                 0
#define USE_DEVICE_SERIAL       0           // in nRF51_disable_peripheral.h
#define ACC_DEVIC               x           // No effect
 *  STEP2
 *      If you equiped the Acc sensor, please check ACC data using folloing definition.
#define USE_ACC                 1
#define CHK_ACC                 1
#define USE_DEVICE_SERIAL       1           // in nRF51_disable_peripheral.h
#define ACC_DEVIC               0 or 1      // depends on your sensor device
 *  STEP3
 *      This is a final setup without no debug information.
#define USE_ACC                 1
#define CHK_ACC                 0
#define USE_DEVICE_SERIAL       0           // in nRF51_disable_peripheral.h
#define ACC_DEVIC               0 or 1      // depends on your sensor device
 *
 */

#define ACC_DEVIC               0   // 0=LIS3DH, 1=BMC050

//  Include ---------------------------------------------------------------------------------------
#include "mbed.h"
#include "BLE.h"
#include "EddystoneService.h"
#if ACC_DEVIC
#include "BMC050.h"
#else
#include "LIS3DH.h"
#endif  // ACC_DEVIC
#include "nRF51_Vdd.h"
#include "nRF51_lowpwr.h"

//  Definition ------------------------------------------------------------------------------------
#define USE_ACC                 0   // if you equipped ACC sensor, please set 1
#define CHK_ACC                 0   // Ckeck ACC device itself

#define POWER_LEVEL             0   // 0,1,2

//  Before using this function, please specify your program are used following functions or not.
#define    USE_DEVICE_STDIO_MESSAGES       0   // printf
#define    USE_DEVICE_SERIAL               0   // Serial or DEBUG & etc.
#define    USE_DEVICE_I2C                  0   // Sensors with I2C, LCD, EEPROM, Driver chips & etc.
#define    USE_DEVICE_SPI                  0   // Sensors with SOI, LCD, EEPROM, Driver chips & etc.
#define    USE_DEVICE_SPISLAVE             0   // Communication with master vis SPI
#define    USE_DEVICE_PWMOUT               0   // PWM duty output, Serve & etc.
#define    USE_DEVICE_ANALOGIN             0   // Analog adc

#if USE_DEVICE_STDIO_MESSAGES
#define DEBUG(...) { printf(__VA_ARGS__); }
#else
#define DEBUG(...)
#endif

#if USE_DEVICE_SERIAL
#define BAUD(x)                 pc.baud(x)
#define GETC(x)                 pc.getc(x)
#define PUTC(x)                 pc.putc(x)
#define PRINTF(...)             { pc.printf(__VA_ARGS__); }
#define READABLE(x)             pc.readable(x)
#define ATTACH(x,y)             pc.attach(x, y);
#else
#define BAUD(x)
#define GETC(x)                 'c'
#define PUTC(x)
#define PRINTF(...)
#define READABLE(x)
#define ATTACH(x,y)
#endif

//  RAM -------------------------------------------------------------------------------------------
EddystoneService        *eddyServicePtr;
Gap::Address_t          my_mac;

//  ROM / Constant data ---------------------------------------------------------------------------
#if (USE_ACC == 1) && (ACC_DEVIC == 1)
const BMC050ACC_TypeDef acc_parameter = {
    BMC050_A_G_CHIP_ADDR, // I2C Address
    BMC050_FS_2G,         // G-range slection 
    BMC050_BW_250,        // Bandwidth
};

const BMC050MAG_TypeDef mag_parameter = {
    BMC050_MAG_NOT_USED_ADDR,// Not use mag sensor
    BMC050_DUMMY          // dummy
};
#endif

const nRF51_LOWPWR_TypeDef lowpwr_table = 
                    {
                    #if USE_DEVICE_STDIO_MESSAGES 
                        true,
                    #else
                        false,
                    #endif
                    #if USE_DEVICE_SERIAL
                        true,
                    #else
                        false,
                    #endif
                    #if USE_DEVICE_I2C
                        true,
                    #else
                        false,
                    #endif
                    #if USE_DEVICE_SPI
                        true,
                    #else
                        false,
                    #endif
                    #if USE_DEVICE_SPISLAVE
                        true,
                    #else
                        false,
                    #endif
                    #if USE_DEVICE_PWMOUT
                        true,
                    #else
                        false,
                    #endif
                    #if USE_DEVICE_ANALOGIN
                        true
                    #else
                        false
                    #endif
                    };

//  Function prototypes ---------------------------------------------------------------------------
int8_t check_dice(void);
uint16_t update_vdd(uint16_t x);
uint16_t update_temp(uint16_t x);
void onBleInitError(BLE::InitializationCompleteCallbackContext* initContext);
void bleInitComplete(BLE::InitializationCompleteCallbackContext* initContext);

//  Object ----------------------------------------------------------------------------------------
DigitalOut  CHG_LED(LED1);
#if USE_DEVICE_SERIAL
Serial      pc(USBTX, USBRX);
#endif  // USE_DEVICE_SERIAL
nRF51_Vdd   vdd(3.6f, 1.8f, ONLY4VDD);
#if USE_ACC == 1
I2C         i2c(P0_3, P0_4); // SDA, SCL
#if ACC_DEVIC
BMC050      acc(i2c, &acc_parameter, &mag_parameter);
#else
LIS3DH      acc(i2c,LIS3DH_G_CHIP_ADDR,LIS3DH_DR_NR_LP_50HZ, LIS3DH_FS_2G);
#endif  // ACC_DEVIC
#endif  // USE_ACC == 1

//-------------------------------------------------------------------------------------------------
//  Control Program
//-------------------------------------------------------------------------------------------------
void bleInitComplete(BLE::InitializationCompleteCallbackContext* initContext){
    BLE         &ble  = initContext->ble;
    ble_error_t error = initContext->error;

    if (error != BLE_ERROR_NONE) {
        onBleInitError(initContext);
        return;
    }
    // Set UID and TLM frame data
    const UIDNamespaceID_t uidNamespaceID =
            {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99};
    const UIDInstanceID_t  uidInstanceID  =
            {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
    uint8_t tlmVersion = 0x00;

    Gap::AddressType_t my_mac_type;
    ble.gap().getAddress(&my_mac_type, my_mac);
    PRINTF(
        "  my_MAC %02x:%02x:%02x:%02x:%02x:%02x (%s)\r\n",
        my_mac[5], my_mac[4], my_mac[3], my_mac[2], my_mac[1], my_mac[0],
        (my_mac_type == Gap::ADDR_TYPE_PUBLIC) ? "public" : "random"
    );
    PRINTF(
        "  mac_board_? = {0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x};\r\n",
        my_mac[0], my_mac[1], my_mac[2], my_mac[3], my_mac[4], my_mac[5]
    );
    // Initialize a EddystoneBeaconConfig service
    // Values for ADV packets related to firmware levels, calibrated based on measured values at 1m
#if POWER_LEVEL == 0
    static const PowerLevels_t defaultAdvPowerLevels = {-47, -33, -21, -13};
#elif POWER_LEVEL == 1
    static const PowerLevels_t defaultAdvPowerLevels = {-87, -73, -61, -53};
#else
    static const PowerLevels_t defaultAdvPowerLevels = {-107, -93, -81, -73};
#endif  // POWER_LEVEL
    // Values for radio power levels, provided by manufacturer.
#if POWER_LEVEL == 0
    static const PowerLevels_t radioPowerLevels      = {-30, -16, -4, 4};
#elif POWER_LEVEL == 1
    static const PowerLevels_t radioPowerLevels      = {-60, -46, -34, -26};
#else
    static const PowerLevels_t radioPowerLevels      = {-90, -76, -64, -56};
#endif  // POWER_LEVEL
    eddyServicePtr = new EddystoneService(ble, defaultAdvPowerLevels, radioPowerLevels);
    // created short cut web addres by http://bitly.oshiire.org/

    switch (check_dice()){
        case 1:
            eddyServicePtr->setURLData("http://bit.ly/1oJh91B");    // Switch sience(mbed)
            break;
        case 2:
            eddyServicePtr->setURLData("http://bit.ly/1oJhP7g");    // switch sience(HP)
            break;
        case 3:
            eddyServicePtr->setURLData("http://bit.ly/1VvuCVr");    // Taiyo Yuden BLE
            break;
        case 4:
            eddyServicePtr->setURLData("http://bit.ly/1Vvtp0l");    // Taiyo Yuden
            break;
        case 5:
            eddyServicePtr->setURLData("http://bit.ly/1Vvt51J");    // JH1PJL(mbed)
            break;
        case 6:
            eddyServicePtr->setURLData("http://bit.ly/1VvteT0");    // JH1PJL(HP)
            break;
        case 0:
        default:
            eddyServicePtr->setURLData("http://mbed.org");
            break;
    }
    eddyServicePtr->setUIDData(&uidNamespaceID, &uidInstanceID);
    eddyServicePtr->setTLMData(tlmVersion);
    eddyServicePtr->onTLMBatteryVoltageUpdate(&update_vdd);
    eddyServicePtr->onTLMBeaconTemperatureUpdate(&update_temp);
    eddyServicePtr->startBeaconService(5, 5, 5);    // Start Eddystone in config mode
}

#if (CHK_ACC == 0)
int main(void){
    uint8_t old_dice;
 
    CHG_LED = 1;
    LowPwr set_lowpwr(&lowpwr_table);
    BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
    ble.init(bleInitComplete);
    while (ble.hasInitialized() == false){;}
    old_dice = check_dice();    // set initial value
    wait(0.5);
    CHG_LED = 0;
    while (true) {
        ble.waitForEvent();
        if (old_dice != check_dice()){
            SCB->AIRCR = 0x05fa0004;    // System RESET!![
            // Not come here (Just in case)
            deepsleep();
            while(true){ wait(100);}
        } 
    }
}
#else   // (CHK_ACC == 0)
#if (USE_ACC == 0)
#error "Please set USE_ACC = 1)
#else   // (USE_ACC == 0)
int main(void){
    float fa[3];

#if (ACC_DEVIC == 1)
    while (true){   
        if (acc.read_id_acc() == I_AM_BMC050_ACC){
            PRINTF("I'm BMC050\r\n");
            acc.read_data_acc(fa);
            break;
        } else {
            PRINTF("I'm NOT BMC050\r\n");
        }
        wait(1.0);
    }
#endif  //  (ACC_DEVIC == 1)
    LowPwr set_lowpwr(&lowpwr_table);
    while (true) {
#if ACC_DEVIC
        acc.read_data_acc(fa);
#else   // ACC_DEVIC
        acc.read_data(fa);
#endif  // ACC_DEVIC
        PRINTF("acc:x=%+4.2f,y=%+4.2f,z=%+4.2f\r\n",fa[0],fa[1],fa[2]);
        wait(0.5);
    }
}
#endif  // (USE_ACC == 0)
#endif  // (CHK_ACC == 0)

#if (USE_ACC == 1)
int8_t check_dice(void){
    float fa[3];    // Acc  0:X, 1:Y, 2:Z

#if ACC_DEVIC
    acc.read_data_acc(fa);
#else   // ACC_DEVIC
    acc.read_data(fa);
#endif  // ACC_DEVIC
    //PRINTF("acc:%4.3f\r\n", fa[0]);
    PRINTF("acc:x=%+4.2f,y=%+4.2f,z=%+4.2f\r\n",fa[0],fa[1],fa[2]);
    if (fa[0] > 6.0f){      return 2;}
    if (fa[0] < -6.0f){     return 5;}
    if (fa[1] > 6.0f){      return 4;}
    if (fa[1] < -6.0f){     return 3;}
    if (fa[2] > 6.0f){      return 1;}
    if (fa[2] < -6.0f){     return 6;}
    return 0;
}
#else   // (USE_ACC == 1)
int8_t check_dice(void){
    return 1;
}
#endif  // (USE_ACC == 1)

void onBleInitError(BLE::InitializationCompleteCallbackContext* initContext){
    // Initialization error handling goes here...
    (void) initContext;
}

// Update Vdd data
uint16_t update_vdd(uint16_t x){
#if USE_DEVICE_SERIAL
    float v;

    v = vdd.read_real_value();
    PRINTF("Vdd:%f[V]\r\n", v);
    return (uint16_t)(v * 1000);
#else   //USE_DEVICE_SERIAL
    return (uint16_t)(vdd.read_real_value() * 1000);
#endif  // USE_DEVICE_SERIAL
}

// Update Temperature data
uint16_t update_temp(uint16_t x){
    float t;
    uint16_t temp;
    int32_t p_temp;

    NRF_TEMP->TASKS_START = 1;
    while (NRF_TEMP->EVENTS_DATARDY == 0){;}
    NRF_TEMP->EVENTS_DATARDY = 0;
    if ((NRF_TEMP->TEMP & 0x00000200) != 0){
        p_temp = (NRF_TEMP->TEMP | 0xFFFFFC00);
    } else {
        p_temp = NRF_TEMP->TEMP;  
    }
    NRF_TEMP->TASKS_STOP = 1; /** Stop the temperature measurement. */
    t = float(p_temp) / 4; // Original = float(p_temp)/4.0f - 16.0f;
#if USE_DEVICE_SERIAL
    PRINTF("Chip temp: %+4.1f[degC]\r\n", t);
#endif // USE_DEVICE_SERIAL
    if ( t >= 0){
        temp = (uint16_t)(t * 256);
    } else {
        temp = (uint16_t)(t * -256);
        temp = 0x10000 - temp;
    }        
    return temp;
}