Project aims to use LED panel controlled through UART with an nucleo STM32 board with shields BLE IDB05A1 & MEMS IKS01A1

Dependencies:   mbed X_NUCLEO_IKS01A2 X_NUCLEO_IDB0XA1 BLE_API

main.cpp

Committer:
waby38
Date:
2017-11-24
Revision:
3:60fe58ad8c7d
Parent:
2:74b8978081c5

File content as of revision 3:60fe58ad8c7d:

/* 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.
 */

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

/* Instantiate the mems expansion board */
static XNucleoIKS01A2 *mems_expansion_board = XNucleoIKS01A2::instance(D14, D15, D4, D5);

/* Retrieve the composing elements of the expansion board */
static LSM303AGRMagSensor *magnetometer = mems_expansion_board->magnetometer;
static HTS221Sensor *hum_temp = mems_expansion_board->ht_sensor;
static LPS22HBSensor *press_temp = mems_expansion_board->pt_sensor;
static LSM6DSLSensor *acc_gyro = mems_expansion_board->acc_gyro;
static LSM303AGRAccSensor *accelerometer = mems_expansion_board->accelerometer;

/* BLE part */
#define UART_BUFFER (UARTService::BLE_UART_SERVICE_MAX_DATA_LEN*10)
const static char DEVICE_NAME[] = "$PANEL$";
UARTService *uartServicePtr;
static char BLEBuffRX[UART_BUFFER];
static uint8_t BLEBuffPos=0;
void onBleError(ble_error_t error);

/* pc uart part */
static char uartBuff[UART_BUFFER];
static uint8_t uartBuffPos=0;
Serial uart1(USBTX,USBRX);
#define DEBUG uart1.printf

/* Led panel part */
#define PANEL_PAGE_NUMBER 26
#define PANEL_PAGE_SIZE 256
Serial uart_panel(PA_9,PA_10);
static uint8_t panel_disppage=0;
static char panel_msg[PANEL_PAGE_NUMBER][PANEL_PAGE_SIZE]={
        "<FE><MA><WC><FE>Bienvenue a STMicroeletronics",
        "<FE><MA><WC><FE>Welcome to STMicroeletronics",
        "<FE><MA><WC><FE>Today is <KD>",
        "<FE><MA><WC><FE>It is <KT>",
        "<FE><MA><WC><FE>Temp is <TEMPERAT>",
        "<FE><MA><WC><FE>I am a <CE>STM32L476",
        "<FE><MA><WC><FE>with <CE>MEMs <CB>and <CE>BLE <CB>shields"
};

typedef enum {
    SCROLL_DEFAULT,
    SCROLL_LEFT,
    SCROLL_RIGHT,
    SCROLL_UP,
    SCROLL_DOWN
} panel_effect_e ;
panel_effect_e panel_effect = SCROLL_DEFAULT;

DigitalOut led1(LED1);
Ticker ticker;

/* Helper function for printing floats & doubles */
static char *printDouble(char* str, double v, int decimalDigits=2)
{
  int i = 1;
  int intPart, fractPart;
  int len;
  char *ptr;

  /* prepare decimal digits multiplicator */
  for (;decimalDigits!=0; i*=10, decimalDigits--);

  /* calculate integer & fractinal parts */
  intPart = (int)v;
  fractPart = (int)((v-(double)(int)v)*i);

  /* fill in integer part */
  sprintf(str, "%i.", intPart);

  /* prepare fill in of fractional part */
    len = strlen(str);
  ptr = &str[len];

  /* fill in leading fractional zeros */
  for (i/=10;i>1; i/=10, ptr++) {
    if(fractPart >= i) break;
    *ptr = '0';
  }

  /* fill in (rest of) fractional part */
  sprintf(ptr, "%i", fractPart);

  return str;
}

void panel_sendmsg(char line, char page, char* text){
    char buff[PANEL_PAGE_SIZE];
    char* pos_t;   
    char* pos_p;
    char* pos_h; 
    char* pos_e; 
    char* panel_reset; 
    uint8_t i, checksum=0;
    pos_t=strstr(text,"<SC>");
    if(pos_t!=0) {
        sprintf(buff,"<ID00>%s",text);
        for(i=6; i<strlen(buff); i++){
            checksum ^= buff[i];
        }
        sprintf(buff,"%s%02X<E>", buff, checksum);
        uart1.printf("panel msg = %s\r\n", buff);
        uart_panel.printf(buff);
        return;
    }  
    sprintf(buff, "<ID00><L%c><P%c>%s", line, page, text);
    pos_t=strstr(buff,"<TEMPERAT>");
    if(pos_t!=0) {
        float sensor_temp;
        char temp[3];
       hum_temp->get_temperature(&sensor_temp);
        sprintf(temp, "%02d", (int)sensor_temp);
        buff[pos_t-buff]=' ';       /* replace < */
        buff[pos_t-buff+1]=temp[0]; /* replace T */
        buff[pos_t-buff+2]=temp[1]; /* replace E */
        buff[pos_t-buff+3]='<';     /* replace M */
        buff[pos_t-buff+4]='U';     /* replace P */
        buff[pos_t-buff+5]='3';     /* replace E */
        buff[pos_t-buff+6]='A';     /* replace R */
        buff[pos_t-buff+7]='>';     /* replace A */
        buff[pos_t-buff+8]='C';     /* replace T */
        buff[pos_t-buff+9]=' ';     /* replace > */
    }
    pos_p=strstr(buff,"<PRESSI>");
    if(pos_p!=0) {
        float sensor_pres;
        char pres[3];
        press_temp->get_pressure(&sensor_pres);
        sprintf(pres, "%02d", (int)sensor_pres);
        buff[pos_p-buff]=' ';       /* replace < */
        buff[pos_p-buff+1]=pres[0]; /* replace P */
        buff[pos_p-buff+2]=pres[1]; /* replace R */
        buff[pos_p-buff+3]='m';     /* replace E */
        buff[pos_p-buff+4]='B';     /* replace S */
        buff[pos_p-buff+5]='a';     /* replace S */
        buff[pos_p-buff+6]='r';     /* replace I */
        buff[pos_p-buff+7]=' ';     /* replace > */

    }
    pos_h=strstr(buff,"<HUM>");
    if(pos_h!=0) {
        float sensor_hum;
        char hum[3];
        hum_temp->get_humidity(&sensor_hum);
        sprintf(hum, "%02d", (int)sensor_hum);
        buff[pos_h-buff]=' ';       /* replace < */
        buff[pos_h-buff+1]=hum[0];  /* replace H */
        buff[pos_h-buff+2]=hum[1];  /* replace U */
        buff[pos_h-buff+3]='\'';    /* replace M */
        buff[pos_h-buff+4]=' ';     /* replace > */
    }
    switch(panel_effect) {
        case SCROLL_RIGHT:
            pos_e=strstr(buff,"<F");
            buff[pos_e-buff+2]='F';
            buff[pos_e-buff+14]='F';
            break;
        case SCROLL_LEFT:
            pos_e=strstr(buff,"<F");
            buff[pos_e-buff+2]='E';
            buff[pos_e-buff+14]='E';
            break;
        case SCROLL_UP:
            pos_e=strstr(buff,"<F");
            buff[pos_e-buff+2]='I';
            buff[pos_e-buff+14]='I';
            break;
        case SCROLL_DOWN:
            pos_e=strstr(buff,"<F");
            buff[pos_e-buff+2]='J';
            buff[pos_e-buff+14]='J';             
            break;
        case SCROLL_DEFAULT: 
            /* No change */
            break;
    }
    panel_reset=strstr(buff,"<RES>");
    if(panel_reset!=0){
        sprintf(buff,"<ID00><D*>");
    }
    
    for(i=6; i<strlen(buff); i++){
        checksum ^= buff[i];
    }
    sprintf(buff,"%s%02X<E>", buff, checksum);
     
    uart1.printf("panel msg = %s pos_d@ %d\r\n", buff, pos_h-buff);
    uart_panel.printf(buff);

    wait(0.1);
    checksum=0;
    if(panel_disppage < page-'A'+1){
        panel_disppage = page-'A'+1;
        sprintf(buff, "<ID00><TA>00010100009912302359");
        
        for(i=0; i<panel_disppage; i++){
            sprintf(buff,"%s%c",buff,i+'A');
        }
        for(i=6; i<strlen(buff); i++){
            checksum ^= buff[i];
        }
        sprintf(buff,"%s%02X<E>", buff, checksum);
        
        uart1.printf("panel msg = %s\r\n", buff);
       
        uart_panel.printf(buff);
    }
}

void periodicCallback(void){  
    int32_t axes[3];
    panel_effect_e new_panel_effect;
    acc_gyro->get_x_axes(axes);
    new_panel_effect = SCROLL_DEFAULT;

  accelerometer->enable();
  acc_gyro->enable_x();

//    DEBUG("accelerometer : %d %d %d\r\n", axes[0], axes[1], axes[2]);
    if(axes[1]<-800){ /* move up */
        new_panel_effect = SCROLL_UP;
    }
    if(axes[1]>800){ /* move down */
        new_panel_effect = SCROLL_DOWN;
    }
    if(axes[0]<-800){ /* move to left */
        new_panel_effect = SCROLL_LEFT;
    }
    if(axes[0]>800){ /* move to right */
        new_panel_effect = SCROLL_RIGHT;
    }
    if(new_panel_effect != panel_effect){
        uint8_t i=0;
       panel_effect=new_panel_effect;
    /*    while(strlen(panel_msg[i])){
            panel_sendmsg('1','A'+i,panel_msg[i]);
            i++;
        }  */
           while(i<26){
            if(strlen(panel_msg[i])){
            panel_sendmsg('1','A'+i,panel_msg[i]);
           }
           i++;
        }  
    }     

}

/* UART */
void uartRx(void)
{
    if(uart1.readable()){
        uartBuff[uartBuffPos] = uart1.getc();
        if((uartBuff[uartBuffPos] == '\r') || (uartBuff[uartBuffPos] == '\n') || (uartBuffPos >= UART_BUFFER)) {
            uartBuff[uartBuffPos] = '\0';
            /* We are sending the whole string even if less than BLE_UART_SERVICE_MAX_DATA_LEN otherwise we need to wait */
            uartServicePtr->write(uartBuff, (uartBuffPos/UARTService::BLE_UART_SERVICE_MAX_DATA_LEN +1) * UARTService::BLE_UART_SERVICE_MAX_DATA_LEN);
            DEBUG("TX : %s\r\n", uartBuff);
            if(uartBuff[0]!='0'){
                strcpy(panel_msg[uartBuff[1]-'A'],&uartBuff[2]);
            }          
            panel_sendmsg(uartBuff[0],uartBuff[1], &uartBuff[2]);
            memset(uartBuff, 0, UART_BUFFER);
            uartBuffPos = 0;       
        }
        else
            uartBuffPos++;
    }
}

/* BLE */
void BleConnectionCallback(const Gap::ConnectionCallbackParams_t *params) {
    DEBUG("BLE Client Connected!\n\r");
    DEBUG("Please type a string and press return\r\n");
    led1 = 1;
}

void BleDisconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
{
    (void)params;
    DEBUG("BLE Client Disconnected!\r\n");
    BLE::Instance().gap().startAdvertising(); // restart advertising
    led1= 0;
}

void BleOnDataWrittenCallback(const GattWriteCallbackParams *params) {
    if (params->handle == uartServicePtr->getTXCharacteristicHandle()){
        DEBUG("RX: %s\r\n", (char *)params->data);
        strncpy(&BLEBuffRX[BLEBuffPos], (char *)params->data, params->len);
        BLEBuffPos+=params->len;
        if((params->len==UARTService::BLE_UART_SERVICE_MAX_DATA_LEN) && (BLEBuffRX[BLEBuffPos-1]!='\n')){
            return;
        }
        BLEBuffRX[BLEBuffPos-1]='\0';
        DEBUG("TX=>Panel: L%c P%c =>%s<=\r\n", BLEBuffRX[0],BLEBuffRX[1], &BLEBuffRX[2]);
        DEBUG("pos dans le pannel %x PANEL_PAGE_NUMBER%d\n\r",BLEBuffRX[1]-'A',PANEL_PAGE_NUMBER);
     if(BLEBuffRX[0]!='0'){
          
         int dippage=BLEBuffRX[1]-'A';       
            DEBUG("disppage: %x BLEBUFFRX=%d\n\r",dippage,BLEBuffRX[1]);
            strcpy(panel_msg[BLEBuffRX[1]-'A'],&BLEBuffRX[2]);
           
           DEBUG("panel_MGS: %s \n\r",panel_msg[26]); 
         }
        panel_sendmsg(BLEBuffRX[0],BLEBuffRX[1], &BLEBuffRX[2]);
        uart1.printf("%c\n",panel_msg);
        BLEBuffPos=0;
        
      
          
    }
   
}


void onBleError(ble_error_t error) { 
    DEBUG("BLE Error: %d\r\n");
    /* Handle error now */
} 

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

    if (error != BLE_ERROR_NONE) {
        /* In case of error, forward the error handling to onBleInitError */
        onBleError(error);
        return;
    }

    /* Ensure that it is the default instance of BLE */
    if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
        return;
    }

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

    DEBUG("BLE UARTService: ");
    /* Setup primary service. */
    UARTService uartService(ble);
    uartServicePtr = &uartService;
    DEBUG("Started\r\n");

    /* setup advertising */
    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().accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    ble.gap().setAdvertisingInterval(500); /* 500ms. */
    ble.gap().startAdvertising();

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

int main(void)
{
    uint8_t i=0;
    led1=0;
    hum_temp->enable();
    press_temp->enable();
    uart_panel.baud(9600);
    uart1.baud(115200);
    uart1.attach(uartRx,Serial::RxIrq);

    /* Init panel */
    while(strlen(panel_msg[i])){
        panel_sendmsg('1','A'+i,panel_msg[i]);
        i++;
    }
    
    ticker.attach(periodicCallback, 2);
    BLE &ble = BLE::Instance();
    ble.init(bleInitComplete);
}