UART BLE tested for IDB05A1 on STM32F411RE - communication between PC terminal and BLE terminal

Dependencies:   mbed X_NUCLEO_IDB0XA1 BLE_API

Fork of BLE_UART_perso by Joël Imbaud

BLE-UART-IDB0XA1.cpp

Committer:
Nthnthj
Date:
2019-11-20
Revision:
12:097314fded0c
Parent:
11:266332086ba5

File content as of revision 12:097314fded0c:

#include "mbed.h"
#include "ble/BLE.h"
#include "ble/services/UARTService.h"
#include "Serial.h"

#define UART_BUFFER (UARTService::BLE_UART_SERVICE_MAX_DATA_LEN*10)

const static char DEVICE_NAME[] = "UART";
UARTService *uartServicePtr;

// Def Peripheriques
DigitalOut Led1(LED1);              // LED
Serial pcUSB(USBTX,USBRX);          // Terminal PC
DigitalIn myButton(USER_BUTTON);    // USER BUTTON


// Tableau et index de communication avec UART
static uint8_t uartBuff[UART_BUFFER];
static uint8_t uartBuffPos=0;

// Routine de traitement des erreurs
void onBleError(ble_error_t error);

// Signal de vie
Ticker LifeTicker;

/****************************************************/
/* Ticker actif lorsque la connexion BLE est présente */
/****************************************************/
void ConnectedBLE(void)
{
    // Signal de vie: allumer et éteindre la LED
    Led1 = !Led1;
}

/***************************/
/* Rx d'USB et Tx vers BLE */
/***************************/
void uartRx(void)
{
    // Capturez les caractères depuis le terminal jusqu'à la fin du message: a '\ r' ou '\ n' ou jusqu'à ce que la taille maximale du message soit atteinte
    if(pcUSB.readable()) {
        uartBuff[uartBuffPos] = pcUSB.getc();
        if((uartBuff[uartBuffPos] == '\r') || (uartBuff[uartBuffPos] == '\n') || (uartBuffPos >= UART_BUFFER)) {
            // insère un NUL dans la dernière position de la chaîne
            uartBuff[uartBuffPos] = '\0';
            // Envoie la chaîne entière même si elle est inférieure à BLE_UART_SERVICE_MAX_DATA_LEN, sinon attente
            uartServicePtr->write(uartBuff, (uartBuffPos/UARTService::BLE_UART_SERVICE_MAX_DATA_LEN +1) * UARTService::BLE_UART_SERVICE_MAX_DATA_LEN);
            // Envoie une confirmation au terminal PC avec la chaîne envoyée au BLE
            pcUSB.printf("TX : %s\r\n", uartBuff);
            // Réinitialiser la chaîne uartBuff en entrant 0 dans les premiers caractères UART_BUFFER
            memset(uartBuff, 0, UART_BUFFER);
            uartBuffPos = 0;
        } else {
            // Si la fin du message n'a pas été atteinte, augmentez le compteur pour recevoir le caractère suivant
            uartBuffPos++;
        }
    }
}

/*************************/
/* Connexion BLE réussie */
/*************************/
void BleConnectionCallback(const Gap::ConnectionCallbackParams_t *params)
{
    pcUSB.printf("BLE Client Connected!\n\r");
    pcUSB.printf("Please type a string and press return\r\n");

    // Signal de connexion BLE: allume / éteint la LED avec une période de 1 seconde
    LifeTicker.attach(ConnectedBLE, 1);
}

/*****************************/
/* Déconnexion du client BLE */
/*****************************/
void BleDisconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
{
    (void)params;
    pcUSB.printf("BLE Client Disconnected!\r\n");
    // Désactiver le signal de connexion BLE: allumer / éteindre la LED avec une période de 1 seconde
    LifeTicker.detach();

    // Redémarrer la publicité
    BLE::Instance().gap().startAdvertising();
    Led1=0;
}

/***************************/
/* Rx de BLE et Rx vers USB*/
/***************************/
void BleOnDataWrittenCallback(const GattWriteCallbackParams *params)
{
    //  Chaîne de réponse en cas de réception pas OK
#define REPLYNOTOK "Rx not Ok :("
    //  Chaîne de réponse en cas de réception OK
#define REPLYOK "Rx Ok :)"
    //  Chaîne de référence
#define REFERENCESTRING "bho"

    char caReply[UART_BUFFER];
    //uint8_t uaAux[UART_BUFFER];
    int nReplyLength;

    // Résultat de la comparaison entre srting
    int nResult;

    // Réinitialiser la chaîne auxiliaire pour composer les réponses
    memset(caReply, 0, UART_BUFFER);

    // Reçoit une chaîne de BLE
    if (params->handle == uartServicePtr->getTXCharacteristicHandle()) {
        // Envoie la chaîne reçue au PC
        pcUSB.printf("RX: %s\r\n", params->data);

        uartServicePtr->write(uartBuff, (uartBuffPos/UARTService::BLE_UART_SERVICE_MAX_DATA_LEN +1) * UARTService::BLE_UART_SERVICE_MAX_DATA_LEN);

    }
}

/***************************/
/* Erreur sur le canal BLE */
/***************************/

void onBleError(ble_error_t error)
{
    pcUSB.printf("BLE Error: %d\r\n");
    /* Entrer le traitement des erreurs */
}

/**************************************/
/* Initialisation du service BLE UART */
/**************************************/

void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
{
    BLE&        ble   = params->ble;
    ble_error_t error = params->error;

    if (error != BLE_ERROR_NONE) {
        
        /* En cas d'erreur, transmettez le traitement d'erreur à onBleInitError*/
        onBleError(error);
        return;
    }

    /* Assurez-vous qu'il s'agit de l'instance par défaut de BLE */
    if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
        return;
    }

    ble.gap().onConnection(BleConnectionCallback);
    ble.gap().onDisconnection(BleDisconnectionCallback);
    ble.gattServer().onDataWritten(BleOnDataWrittenCallback);

    pcUSB.printf("BLE UARTService: ");
    
    /* Configuration du service primaire. */
    UARTService uartService(ble);
    uartServicePtr = &uartService;
    
    pcUSB.printf("Started\r\n");

    /* Configurer la publicité */
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed));
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    ble.gap().setAdvertisingInterval(500); /* 500ms. */
    ble.gap().startAdvertising();

    // Attend les événements sur BLE
    while (true) {
        ble.waitForEvent();
    }
}

/********/
/* MAIN */
/********/
int main(void)
{

    // Configurer la vitesse de communication série sur USB-VirtualCom et envoyer un message de bienvenue
    pcUSB.baud(9600); //9600 bps
    
    // Message de bienvenue
    pcUSB.printf("\r\n***  Bluetooth to PC serial communication  ***\r\n");

    //Définit le fonctionnement du bouton sur "PullDown": Open = '0'. L’autre mode de fonctionnement est PullUp
    myButton.mode(PullDown);
    
    // Initialiser LED
    Led1=0;

    // IRQ associée à la réception de caractères de série à USB depuis un PC
    pcUSB.attach(uartRx,Serial::RxIrq);

    /****** START Initialiser BLE **********/
    BLE &ble = BLE::Instance();
    ble.init(bleInitComplete);
    /******* FIN initialise BLE ***********/
}