Diseño de Firmaware Diseañado en base a los requerimientos definidos durante la etapa de analisis.

Dependencies:   BLE_API mbed

Fork of nRF51822_SimpleControls by Gustavo Belduma

main.cpp

Committer:
Gustavo_Eduardo338
Date:
2016-08-17
Revision:
8:c4130ea78471
Parent:
7:fb4c6c1dd3a9
Child:
9:501a9e6710d2

File content as of revision 8:c4130ea78471:

/*
Copyright (c) 2012-2014 RedBearLab

Permission is hereby granted, free of charge, to any person obtaining a copy of this software
and associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

*/

#include "mbed.h"
#include "ble/BLE.h"
#include "GattCallbackParamTypes.h"

#define BLE_UUID_TXRX_SERVICE            0x0000 /**< The UUID of the Nordic UART Service. */
#define BLE_UUID_TX_CHARACTERISTIC       0x0002 /**< The UUID of the TX Characteristic. */
#define BLE_UUIDS_RX_CHARACTERISTIC      0x0003 /**< The UUID of the RX Characteristic. */

#define TXRX_BUF_LEN                     20

#define DIGITAL_OUT_7                    P0_17  //D7
#define DIGITAL_OUT_8                    P0_19  //D8
#define DIGITAL_OUT_11                   P0_12  //D11
#define DIGITAL_OUT_4                    P0_21  //D4

#define DIGITAL_IN_PIN                   P0_5   //A4

#define PWM_PIN                          P0_16  //D6
#define ANALOG_IN_PIN                    P0_6   //A5

// Declarando los pines
//static int32_t send_config = 0;
static int32_t enviar_config_01 = 0;

// variables semaforos que me permiten identificar si se debe o no enviar las tramas de configuracion de cada sensor.
static int32_t sen_analog_in_5 = 0;
static int32_t sen_digital_in_7 = 0;
static int32_t act_analog_out_6 = 0;
static int32_t act_analog_out_4 = 0;
static int32_t act_analog_out_7 = 0;

// Variables semaforo que me permiten identificar si se debe enviar la respuesta de confirmacion
static int32_t resp_analog_out_6 = 0;
static int32_t resp_digital_out_4 = 0;
static int32_t resp_digital_out_7 = 0;

BLE ble;

// Digital IN
DigitalIn       BUTTON(DIGITAL_IN_PIN);

// Digital OUT
DigitalOut      LED_SET_D7(DIGITAL_OUT_7);
DigitalOut      LED_SET_D8(DIGITAL_OUT_8);
DigitalOut      LED_SET_D11(DIGITAL_OUT_11);
DigitalOut      LED_SET_D4(DIGITAL_OUT_4);

// Analog IN
AnalogIn        ANALOG(ANALOG_IN_PIN);

// Analog OUT
PwmOut          PWM(PWM_PIN);

// Permite imprimir mensajes en la consola
Serial pc(USBTX, USBRX);

static uint8_t analog_enabled = 0;
static uint8_t old_state = 0;

// The Nordic UART Service
static const uint8_t uart_base_uuid[] = {0x71, 0x3D, 0, 0, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
static const uint8_t uart_tx_uuid[]   = {0x71, 0x3D, 0, 3, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
static const uint8_t uart_rx_uuid[]   = {0x71, 0x3D, 0, 2, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
static const uint8_t uart_base_uuid_rev[] = {0x1E, 0x94, 0x8D, 0xF1, 0x48, 0x31, 0x94, 0xBA, 0x75, 0x4C, 0x3E, 0x50, 0, 0, 0x3D, 0x71};

// Trama de Configuracion de los Pines (a).
static const uint8_t di_conf  [] = {0xC01,0xA1, 20, 0xA0, 40, 0xD1, 10, 0xD0, 90};        // length: 9

uint8_t txPayload[TXRX_BUF_LEN] = {0,};
uint8_t rxPayload[TXRX_BUF_LEN] = {0,};

GattCharacteristic  txCharacteristic (uart_tx_uuid, txPayload, 1, TXRX_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE);
GattCharacteristic  rxCharacteristic (uart_rx_uuid, rxPayload, 1, TXRX_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
GattCharacteristic *uartChars[] = {&txCharacteristic, &rxCharacteristic};
GattService         uartService(uart_base_uuid, uartChars, sizeof(uartChars) / sizeof(GattCharacteristic *));

// https://developer.mbed.org/forum/repo-61676-BLE_GAP_Example-community/topic/17193/
void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *)
{
    BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
    pc.printf("Disconnected \r\n");
    pc.printf("Restart advertising \r\n");
    ble.startAdvertising();
    LED_SET_D11 = 0;
    analog_enabled = 0;         //  Deja que envie lecturas el PT 1000
    
    sen_analog_in_5 = 0;
    sen_digital_in_7 = 0;
    act_analog_out_6 = 0;
    act_analog_out_4 = 0;
    act_analog_out_7 = 0;
    
    enviar_config_01 = 0;
}
// Ingresa por este metdo unicamente la primera vez que se conecta al mote.
// Tomado desde: https://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_LEDBlinker/file/dc392bde2b3c/main.cpp
void connectionCallback(const Gap::ConnectionCallbackParams_t *)
{
    pc.printf("connectionCallback \r\n");
    LED_SET_D11 = 1;                //  Enciendo led que indica que alguien se conecto
    enviar_config_01 = 1;
    //send_config = 1;
}

// Recepta las caracteristicas que se desea escribir en el mote.
void WrittenHandler(const GattWriteCallbackParams *Handler)
{
    pc.printf("WrittenHandler(const GattWriteCallbackParams *Handler) \r\n");
    uint8_t buf[TXRX_BUF_LEN];
    uint16_t bytesRead, index;

    if (Handler->handle == txCharacteristic.getValueAttribute().getHandle()) {
        ble.readCharacteristicValue(txCharacteristic.getValueAttribute().getHandle(), buf, &bytesRead);
        memset(txPayload, 0, TXRX_BUF_LEN);
        memcpy(txPayload, buf, TXRX_BUF_LEN);

        //por dixys
        pc.printf("Buffer recibido desde Android: \r\n");

        for(index=0; index<bytesRead; index++)
            pc.putc(buf[index]);

        pc.printf("Leemos la trama: \r\n");
        for(index=0; index<bytesRead; index++) {
            pc.printf("buf[%02x]: %02x\r\n", index, buf[index]);

        }
        pc.printf("Fin de la Lectura: \r\n");

        // Desde el telefono desactiva el envio de tramas de las siguientes tramas.
        if (buf[0] == 0xDC && buf[1] == 0xC1) {              //  Dato Configuracion
            enviar_config_01 = buf[2];      // Debe ser cero, hace que ya no se vuelva a enviar la conf general del mote
            sen_analog_in_5 = 1;            // habilita al Sensor PT1000, para que envie su configuracion
        }
        //  PT 1000
        if (buf[0] == 0xDC && buf[1] == 0x05 && buf[2] == 0xAA && buf[3] == 20) {
            sen_analog_in_5 = buf[4];       // Hace que ya no se vuelva a enviar este tipo de configuracion
            sen_digital_in_7 = 1;           //  habilita al Sensor de Luz, para que envie su configuracion
        }
        //  sensor de luz
        if (buf[0] == 0xDC && buf[1] == 0x05 && buf[2] == 0xDD && buf[3] == 10) {
            sen_digital_in_7 = buf[4];      // Hace que ya no se vuelva a enviar este tipo de configuracion
            act_analog_out_6 = 1;           //  habilita al atuador PWD, para que envie su configuracion
        }
        
        //  PWD
        if (buf[0] == 0xDC && buf[1] == 0xA && buf[2] == 0xAA && buf[3] == 40) {
            act_analog_out_6 = buf[4];      // Hace que ya no se vuelva a enviar este tipo de configuracion
            act_analog_out_4 = 1;           //  habilita al atuador Bomba, para que envie su configuracion
        }
        //  Actuador la Bomba
        if (buf[0] == 0xDC && buf[1] == 0xA && buf[2] == 0x0A && buf[3] == 80) {
            act_analog_out_4 = buf[4];      // Hace que ya no se vuelva a enviar este tipo de configuracion
            act_analog_out_7 = 1;           //  habilita al atuador Foco, para que envie su configuracion
        
        }
        //  Actuador Foco
        if (buf[0] == 0xDC && buf[1] == 0xA && buf[2] == 0x0A && buf[3] == 10) {
            act_analog_out_7 = buf[4];       // Hace que ya no se vuelva a enviar este tipo de configuracion
        }
        
        //  Maneja las Tramas de confirmacion
        //  PWD
        if (buf[0] == 0xBB && buf[1] == 0xA0 && buf[2] == 40) {
            resp_analog_out_6 = buf[3];      // Hace que ya no se vuelva a enviar este tipo de configuracion
        }
        //  Actuador la Bomba
        if (buf[0] == 0xBB && buf[1] == 0xD0 && buf[2] == 80) {
            resp_digital_out_4 = buf[3];      // Hace que ya no se vuelva a enviar este tipo de configuracion
        
        }
        //  Actuador Foco
        if (buf[0] == 0xBB && buf[1] == 0xD0 && buf[2] == 10) {
            resp_digital_out_7 = buf[3];
        }

        // Verifico si es una trama de Escitura.
        if(buf[0] == 0xEE) {
            // Verifico si es un signal Digital Out
            if(buf[2] == 0xD0) {
                if(buf[3] == 0x07 && buf[4] == 0x01) {
                    LED_SET_D7 = 1;
                    resp_digital_out_7 = buf[1];        //  Paquete id
                } else {
                    LED_SET_D7 = 0;
                    resp_digital_out_7 = buf[1];        //  Paquete id
                }

                if(buf[3] == 0x04 && buf[4] == 0x01) {
                    LED_SET_D4 = 1;
                    analog_enabled = 1;
                    resp_digital_out_4 = buf[1];        //  Paquete id
                } else {
                    LED_SET_D4 = 0;
                    analog_enabled = 0;
                    resp_digital_out_4 = buf[1];        //  Paquete id
                }
            // Verifico si es un signal Analog out
            } else if(buf[2] == 0xA0) {
                if(buf[3] == 0x06) {
                    float value = (float)buf[4]/255;
                    PWM = value;
                    pc.printf("PWM = %f  \r\n", value);
                    resp_analog_out_6 = buf[1];        //  Paquete id
                }
            }
        
        } else if(buf[0] == 0xA0) {
            if(buf[1] == 0x01) {
                analog_enabled = 1;
                //por dixys
                pc.printf("ANALOG ENABLE \r\n");
            } else {
                analog_enabled = 0;
                // lo vamos a poner fio enable para hacer pruebas luego lo quitamos
                //por dixys
                pc.printf("ANALOG DISAABLE \r\n");
                pc.printf("valor : %d", analog_enabled);
            }
        } else if(buf[0] == 0x02) {
            float value = (float)buf[1]/255;
            PWM = value;
            //por dixys
            pc.printf("PWM = %f  \r\n", value);
        } else if(buf[0] == 0x03) {
            //MYSERVO.write(buf[1]);
            //por dixys
            pc.printf("SERVO buffer  \r\n");
        } else if(buf[0] == 0x04) {
            analog_enabled = 0;
            PWM = 0;
            //MYSERVO.write(0);
            LED_SET_D7 = 0;
            old_state = 0;
            //por dixys
            pc.printf("opcion 4 \r\n");
        }
    }
}

/*
* Desde este metodo envia las tramas al Gateway.
*/
void m_status_check_handle(void)
{
    uint8_t tiempo_entre_envio_conf = 200;
    uint8_t buf[5], conf_02[5];
    conf_02[0] = (0xC02);               //  Codigo que indica que la configuracion sera por cada Pin.

    if (analog_enabled) { // if analog reading enabled
        pc.printf("analog_enabled: %d\r\n", analog_enabled);
        // Read and send out
        float s = ANALOG;
        pc.printf("value pt 1000 (s): %d\r\n", s);
        uint16_t value = s*1024;
        buf[0] = (0xDD);                    //  Codigo
        buf[1] = (0x00);                    //  paquete id
        buf[2] = (0xA1);                    //  A1| A0| D1| D0
        buf[3] = (20);                      //  Posicion
        buf[4] = (value);                   //  Valor
        pc.printf("value pt 1000: %d\r\n", value);  // Imprimo en terminal lo que esta enviando desde el mote.

        ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, 5);    // Para el RTD
    }

    // If digital in changes, report the state
    if (BUTTON != old_state) {
        old_state = BUTTON;
        buf[0] = (0xDD);                    //  Codigo de Lecturas de Datos.
        buf[1] = (0x00);                    //  Paquete
        buf[2] = (0xD1);                    //  A1| A0| D1| D0
        buf[3] = (10);                       //  Posicion
        if (BUTTON == 1) {
            pc.printf("BUTTON == 1\r\n");
            LED_SET_D7 = 0;
            buf[4] = (0x00);    //  Valor
        } else {
            pc.printf("else BUTTON == 1 \r\n");
            LED_SET_D7 = 1;
            buf[4] = (0x01);    //  Valor
        }
        ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, 5);
    }

    //pc.printf("enviar_config %d \r\n", enviar_config_01);
    if (enviar_config_01 == 1) {
        //  Envia la configuracion Genaral del Mote.
        pc.printf("enviar_config_01 %d \r\n", enviar_config_01);
        ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), di_conf, 9);
    }
    
    //  Envia la configuracion del PT 1000.
    if (sen_analog_in_5 == 1) {
        conf_02[1] = (0x05);                 //  Categoria puede ser: A (Actuador) | 5 (Sensor)
        conf_02[2] = (0xAA);                 //  Tipo de Signal AA | DD
        conf_02[3] = (37);                   //  Codigo del Ted
        conf_02[4] = (20);                   //  Posicion que ocupa en el mote

        pc.printf("Configuracion Detallada por Pin PT1000\r\n");
        ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), conf_02, 5);
    }
    
    //  Envia la configuracion del sensor de luz.
    if (sen_digital_in_7 == 1) {
        conf_02[1] = (0x05);                 //  Categoria puede ser: A (Actuador) | 5 (Sensor)
        conf_02[2] = (0xDD);                 //  Tipo de Signal AA | DD
        conf_02[3] = (30);                    //  Codigo del Ted
        conf_02[4] = (10);                   //  Posicion que ocupa en el mote

        pc.printf("Configuracion Detallada por sensor de luz\r\n");
        ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), conf_02, 5);
    }
    
    //  Envia la configuracion del PWD.
    if (act_analog_out_6 == 1) {
        conf_02[1] = (0xA);                 //  Categoria puede ser: A (Actuador) | 5 (Sensor)
        conf_02[2] = (0xAA);                 //  Tipo de Signal AA | DD
        conf_02[3] = (0);                    //  Codigo del Ted
        conf_02[4] = (40);                   //  Posicion que ocupa en el mote

        pc.printf("Configuracion Detallada por PWD\r\n");
        ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), conf_02, 5);
    }
    
    //  Envia la configuracion del Actuador la Bomba.
    if (act_analog_out_4 == 1) {
        conf_02[1] = (0xA);                 //  Categoria puede ser: A (Actuador) | 5 (Sensor)
        conf_02[2] = (0x0A);                //  Tipo de Signal AA | DD
        conf_02[3] = (0);                   //  Codigo del Ted
        conf_02[4] = (80);                  //  Posicion que ocupa en el mote

        pc.printf("Configuracion Detallada por Actuador la Bomba \r\n");
        ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), conf_02, 5);
    }
    
    //  Envia la configuracion del Actuador Foco.
    if (act_analog_out_7 == 1) {
        conf_02[1] = (0xA);                 //  Categoria puede ser: A (Actuador) | 5 (Sensor)
        conf_02[2] = (0x0A);                 //  Tipo de Signal AA | DD
        conf_02[3] = (0);                    //  Codigo del Ted
        conf_02[4] = (10);                   //  Posicion que ocupa en el mote

        pc.printf("Configuracion Detallada por Actuador Foco \r\n");
        ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), conf_02, 5);
    }
    
    // Envia las tramas de confirmacion hacia el gateway.
    if (resp_analog_out_6 != 0){
        // Envia trama de lectura
        buf[0] = (0xDD);                    //  Codigo
        buf[1] = resp_analog_out_6;         //  paquete id
        buf[2] = (0xA0);                    //  A1| A0| D1| D0
        buf[3] = (40);                      //  Posicion
        buf[4] = PWM;                       //  Valor
        pc.printf("resp_analog_out_6 %d\r\n", resp_analog_out_6);  // Imprimo en terminal lo que esta enviando desde el mote.

        ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, 5);    // Para el RTD
    }
    
    if (resp_digital_out_4 != 0){
        // Envia trama de lectura
        buf[0] = (0xDD);                    //  Codigo
        buf[1] = resp_digital_out_4;         //  paquete id
        buf[2] = (0xD0);                    //  A1| A0| D1| D0
        buf[3] = (80);                      //  Posicion
        buf[4] = LED_SET_D4;                       //  Valor
        pc.printf("resp_digital_out_4 %d\r\n", resp_digital_out_4);  // Imprimo en terminal lo que esta enviando desde el mote.

        ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, 5);    // Para el RTD
    }
    
    if (resp_digital_out_7 != 0){
        // Envia trama de lectura
        buf[0] = (0xDD);                    //  Codigo
        buf[1] = resp_digital_out_7;         //  paquete id
        buf[2] = (0xD0);                    //  A1| A0| D1| D0
        buf[3] = (10);                      //  Posicion
        buf[4] = LED_SET_D7;                       //  Valor
        pc.printf("resp_digital_out_7 %d\r\n", resp_digital_out_7);  // Imprimo en terminal lo que esta enviando desde el mote.

        ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, 5);    // Para el RTD
    }

    wait_ms(100);
}

int main(void)
{
    Ticker ticker;
    ticker.attach_us(m_status_check_handle, 200000);

    ble.init();
    ble.onDisconnection(disconnectionCallback);
    ble.onConnection(connectionCallback);
    ble.onDataWritten(WrittenHandler);

    pc.baud(9600);
    pc.printf("SimpleChat Init \r\n");
    //pc.attach( uartCB , pc.RxIrq);

    // setup advertising
    ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
    ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,
                                     (const uint8_t *)"Biscuit", sizeof("Biscuit") - 1);   // Original:  Biscuit
    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
                                     (const uint8_t *)uart_base_uuid_rev, sizeof(uart_base_uuid));
    // 100ms; in multiples of 0.625ms.
    ble.setAdvertisingInterval(160);

    ble.addService(uartService);

    ble.startAdvertising();

    pc.printf("Advertising Start \r\n");

    //por dixys
    // para probar, luego quitar. Esto hace que cada ticker se envie un dato analogico via BLE
    analog_enabled = 0;

    while(1) {
        ble.waitForEvent();
    }
}