CAN to BLE translator - and back

Dependencies:   BLE_API CANnucleo X_NUCLEO_IDB0XA1 mbed

main.cpp

Committer:
filippomontano
Date:
2016-04-12
Revision:
7:b834d20f9aa1
Parent:
6:f85bc6e59111

File content as of revision 7:b834d20f9aa1:

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

#define TARGET_NUCLEO_F072RB 1
#define   LED_PIN   PA_5

#define BLE_GATT_CHAR_PROPERTIES_NOTIFY 0x10

uint8_t CANId2BLESlot(unsigned int   id);
unsigned int BLESlot2CANId(uint8_t   id);
void onMsgReceived(void);

void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params);
void writeCharCallback(const GattWriteCallbackParams  *params);
void bleInitComplete(BLE::InitializationCompleteCallbackContext *params);
void onBleInitError(BLE &ble, ble_error_t error);

void periodicCallback(void);


void initMEM(void);
void dumpMEM(void);

CANMessage      rxMsg;
CANMessage      txMsg;

BLE ble;

char shareddata[64][8]= { };

DigitalOut      led(LED_PIN),CAN_show(PC_12);
DigitalIn button(PC_13);

const uint8_t firstBleRdPointer=1;
const uint8_t lastBleRdPointer=14;
const uint8_t firstCanRdPointer=57;
const uint8_t lastCanRdPointer=63;

const static char     DEVICE_NAME[]        = "STNucleo - RGM - FM";
const static uint16_t uuid16_list[]        = {0xFFFF};

static volatile bool  triggerSensorPolling = false;

uint8_t canWrPointer= 255;
uint8_t canRdPointer= 255;
uint8_t bleWrPointerA= 255;
uint8_t bleRdPointerA= 255;
uint8_t bleWrPointerB= 255;
uint8_t bleRdPointerB= 255;

uint8_t canRdLastPointer= 255; // puntatore per sapere che cosa ho mandato per ultimo. a runtime devo andare a modificarlo per sapere al ciclo dopo cosa ho già mandato
uint8_t bleRdLastPointer= 255; // puntatore per sapere che cosa ho mandato per ultimo. a runtime devo andare a modificarlo per sapere al ciclo dopo cosa ho già mandato

Ticker ticker;      //synchronous counter - IRQ enabled
Timer           timerA; //unsynchronous counter  - no IRQ 

//CAN             can(PB_8, PB_9);  // alternatives for CAN Rx pin name, CAN Tx pin name

uint16_t customServiceUUID  = 0xA000; // service UUID
uint16_t readCharUUID       = 0xA001; // read characteristic UUID
uint16_t writeCharUUID      = 0xA002; // write characteristic UUID

static uint8_t readValue[128] = {0};
ReadOnlyArrayGattCharacteristic<uint8_t,  sizeof(readValue)> readChar(readCharUUID, readValue, BLE_GATT_CHAR_PROPERTIES_NOTIFY , NULL,0); //aggiunto il BLE_GATT_CHAR_PROPERTIES_NOTIFY => appena arriva lo rimanda

static uint8_t writeValue[128] = {0};
WriteOnlyArrayGattCharacteristic<uint8_t, sizeof(writeValue)> writeChar(writeCharUUID, writeValue);

GattCharacteristic *characteristics[] = {&readChar, &writeChar};
GattService         customService(customServiceUUID, characteristics,  sizeof(characteristics) / sizeof(GattCharacteristic *));

uint8_t retry=1;
char symbol=' ';

volatile bool   CANmsgAvailable = false;
volatile bool   BLExmit = false;
bool signal=true;

float stopTimer=2.0;

uint8_t readdata[20]= {}; //BLE data
char kantMsg[8]= {0};   //CAN data

int main()
{
    uint8_t j=0,k=0;
    int mcan=0;
    initMEM();
    printf("\r\nBoard started\r\n");
    led = 1;       // turn LED on
    bleRdLastPointer=lastBleRdPointer;
    canRdPointer=lastCanRdPointer;
    BLE::Instance().init(bleInitComplete);
    CAN             can(PA_11, PA_12);  // CAN Rx pin name, CAN Tx pin name

    //canRdLastPointer=lastCanRdPointer;
    can.frequency(500000);                     // set bit rate to 500kbps as S018
    printf("CAN started at 500kbps\r\n");
    timerA.start();
    can.attach(&onMsgReceived, CAN::RxIrq);     // attach 'CAN receive-complete' interrupt handler
    while(true) {
        //  if(ble.getGapState().connected) {
        if(triggerSensorPolling && ble.getGapState().connected) {
            triggerSensorPolling=false;
        } else {
            ble.waitForEvent();
        }

        if(ble.gap().getState().connected) {
            stopTimer=0.1;

        } else {

            stopTimer=1;
            //stopTimer=5;
            //  ble.waitForEvent();

        }

        if(timerA.read()>=stopTimer) {
            //   BLExmit=ble.getGapState().connected;
            BLExmit=ble.gap().getState().connected;
            timerA.stop();
            timerA.reset();
            led=!led.read();
            timerA.start();
            if(!button) dumpMEM();
            
            
            if(++canRdPointer>lastCanRdPointer) {
                canRdPointer=firstCanRdPointer;
             }
            mcan = BLESlot2CANId(canRdPointer);
             for(int m=0; m<8; m++) {
                kantMsg[m] = shareddata[canRdPointer][m];
            }
            if(can.write(CANMessage(mcan, kantMsg, 8))) {              // transmit message
            //if(can.write(txMsg)) {              // transmit message
           //     printf("CAN message sent %x, 0x%.3x",canRdPointer, mcan);
             //    for(int c=0; c<8; c++) {
             //        printf(" %.2x",kantMsg[c]);
             //    }
             //    printf("\r\n");
            }


        }
        if(CANmsgAvailable) {
            CANmsgAvailable = false;               // reset flag for next use
            can.read(rxMsg);                    // read message into Rx message storage
            j=CANId2BLESlot(rxMsg.id);
            if(j!=bleRdPointerA && j!=bleRdPointerB) {
                //  printf("CAN message rcvd %.2x, 0x%.3x \r\n",j,rxMsg.id);
                for(int i = 0; i < rxMsg.len; i++) {
                    shareddata[j][i]=rxMsg.data[i];
                    // printf(" %.2x",rxMsg.data[i]);
                }
                //printf("\r\n");
            }
        }
        if(BLExmit) {
            BLExmit=false;
            retry++;
            if(retry==0xff) ble.gap().startAdvertising();
          //  printf ("%#x  ",retry);
            k++;
            if(k>lastBleRdPointer)
                k=firstBleRdPointer;
            readValue[0]=k;
          //  printf (" <%.2x ---",readValue[0]);
            for(int i=1; i<8; i++) {
                readValue[i]=shareddata[k][i];
          //      printf ("%.2x ",readValue[i]);
            }
            readValue[8]= ++k;;
          //  printf ("> <%.2x ---",readValue[8]);

            for(int i=9; i<18; i++) {
                readValue[i]=shareddata[k][i-9];
           //     printf ("%.2x ",readValue[i]);
            }
           // printf (">\n\r");
            ble.updateCharacteristicValue(readChar.getValueHandle(), readValue,18);
        }
    }
}

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

    if (error != BLE_ERROR_NONE) {
        onBleInitError(ble, error);
        return;
    }

    if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
        return;
    }

    ble.gap().onDisconnection(disconnectionCallback);

    /* Setup primary service. */

    /* Setup advertising. */
    printf("Setup of BLE Advertising\r\n");
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    ble.gap().setAdvertisingInterval(1000);// 1000ms
    ble.gap().startAdvertising();
    ble.onDataWritten(writeCharCallback);
    ble.addService(customService);
    ticker.detach();
    ticker.attach(periodicCallback, 1); // blink LED every second

    printf("Starting Loop\r\n");


}
void onBleInitError(BLE &ble, ble_error_t error)
{
    (void)ble;
    (void)error;
    printf(" ### BLE init error ###\r\n");


    /* Initialization error handling should go here */
}
void onMsgReceived(void)
{
    CANmsgAvailable = true;
}

void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
{
    (void)params;
    printf("\r\nTarget loss... wait for reconnection \r\n");

    BLE::Instance().gap().startAdvertising(); // restart advertising
    dumpMEM();
}

void writeCharCallback(const GattWriteCallbackParams  *params)
{

    uint8_t j=0;

    // check to see what characteristic was written, by handle
    if(params->handle  == writeChar.getValueHandle()) {
        j= BLESlot2CANId(params->data[0]);
        printf("\n\r Data received: length = %d, data = ",params->len);
        if(canRdPointer != j && canRdPointer != j+1) {
            bleWrPointerA=j;
            bleWrPointerB=j+1;
            for(int x=0; x < 9; x++) {
                printf("%c",params->data[x]);
                shareddata[j][x]=params->data[x];
            }
            for(int x=9; x < 18; x++) {
                printf("%c",params->data[x]);
                shareddata[j+1][x-9]=params->data[x];
            }
            bleWrPointerA=255;
            bleWrPointerB=255;
        }
    }
}
void periodicCallback(void)
{
    if(!ble.getGapState().connected) {
        printf("? ");
        ticker.attach(periodicCallback, 1); // blink LED every 5 second
    } else
        ticker.attach(periodicCallback, 0.1); // blink LED every second

    triggerSensorPolling = true;
}

uint8_t CANId2BLESlot(unsigned int   id)
{
    uint8_t retval=0;
    switch(id) {
        case 0x313:
            retval=1;
            break;
        case 0x314:
            retval=2;
            break;
        case 0x310:
            retval=3;
            break;
        case 0x315:
            retval=4;
            break;
        case 0x111:
            retval=5;
            break;
        case 0x112:
            retval=6;
            break;
        case 0x400:
            retval=7;
            break;
        case 0x450:
            retval=8;
            break;
        case 0x451:
            retval=9;
            break;
        case 0x452:
            retval=10;
            break;
        case 0x453:
            retval=11;
            break;
        case 0x454:
            retval=12;
            break;
        case 0x455:
            retval=13;
            break;
        default:
            retval=0;
            break;
    }
    return retval;
}
unsigned int BLESlot2CANId(uint8_t   id)
{
    unsigned int retval=0;
    switch(id) {
        case 63:
            retval=0x301;
            break;
        case 62:
            retval=0x302;
            break;
        case 61:
            retval=0x303;
            break;
        case 60:
            retval=0x304;
            break;
        case 59:
            retval=0x101;
            break;
        case 58:
            retval=0x102
            ;
            break;
        case 57:
            retval=0x040;
            break;
        default:
            retval=0x0;
            break;
    }
    return retval;
}
void initMEM(void)
{
    for(int im = 0; im<64; im++) {
        for (int jm=0; jm<8; jm++) {
            shareddata[im][jm]=0x00;
        }
    }
    for (int jm=0; jm<8; jm++) {
        kantMsg[jm]=0;
    }
}
void dumpMEM(void)
{
    printf("\r\n --- Memory Dump ---");
    for(int im = 0; im<64; im++) {
        printf("\r\n%.2x", im);
        for (int jm=0; jm<8; jm++) {
            printf(" %.2x", shareddata[im][jm]);
        }
    }
    printf("\r\n --- End of Dump ---\r\n");
}