desloges-libioulle / Mbed 2 deprecated app3_coordinator

Dependencies:   mbed-rtos mbed EthernetInterface

main.cpp

Committer:
libv2001
Date:
2017-02-12
Revision:
2:ff0b74e5e62c
Parent:
0:671a7b7e4673
Child:
3:05ba7be59773

File content as of revision 2:ff0b74e5e62c:

#include "mbed.h"
#include "rtos.h"
#include "xbee.h"

#define nullptr 0

DigitalOut myled(LED1);

Serial pc(USBTX, USBRX);

Serial *xbee;
DigitalOut *xbeeRst;

const int HARDWARE_RESET_SIGNAL =      0x10;
const int COORDINATOR_STARTED_SIGNAL = 0x20;
const int TICKER_SIGNAL =              0x40;
const int RESPONSE_SIGNAL =            0x80;

Thread * XBeeConsumer;
Thread * XBeeProducer;
Thread * EventConsumer;
Ticker timer;

int responseStatus;

char * BTN_ID = "BTN";
char * ACC_ID = "ACC";

struct ButtonEvent{
    char id[3];
    bool state;
};

struct AccelerometerEvent {
    char id[3];
    char x[2], y[2], z[2];
};

MemoryPool<ButtonEvent, 32> btnPool;
MemoryPool<AccelerometerEvent, 32> accPool;
Queue<void, 64> event;

struct Rooter{
    long long int addr64;
    short addr16;
    
    bool operator==(const Rooter & rhs){
        return addr64 == rhs.addr64 && addr16 == rhs.addr16;
    }
};

#define ROOTER_MAX 2
Rooter rooters[ROOTER_MAX];
int rooterCount = 0;

Mutex rooterMutex;
/*******************************************************/
/**********************UTILITIES************************/
/*******************************************************/

PinName GetPinName(const int p){
    switch(p){
        case 5: return p5;
        case 6: return p6;
        case 7: return p7;
        case 8: return p8;
        case 9: return p9;
        case 10: return p10;
        case 11: return p11;
        case 12: return p12;
        case 13: return p13;
        case 14: return p14;
        case 15: return p15;
        case 16: return p16;
        case 17: return p17;
        case 18: return p18;
        case 19: return p19;
        case 20: return p20;
        case 21: return p21;
        case 22: return p22;
        case 23: return p23;
        case 24: return p24;
        case 25: return p25;
        case 26: return p26;
        case 27: return p27;
        case 28: return p28;
        case 29: return p29;
        case 30: return p30;
    }
    pc.printf("Numero de pin invalid");
    return NC;
}

/*******************************************************/
/***********************CONFIG**************************/
/*******************************************************/
int panID;
int xbeeTxPin;
int xbeeRxPin;
int xbeeRstPin;
char server[16];

char key[10];

LocalFileSystem local("local");

void ReadConfig(){
    memset(server, 0x00, 16);
    FILE * f = fopen("/local/coord.cfg", "r");
    fscanf(f,"%s %x", key, &panID);
    pc.printf("Config started\r\n");
    pc.printf("Lecture de la config %s : %04x\r\n", key, panID);
    fscanf(f,"%s %d %d %d", key, &xbeeTxPin, &xbeeRxPin, &xbeeRstPin);
    pc.printf("Lecture de la config %s : %d %d %d\r\n", key, xbeeTxPin, xbeeRxPin, xbeeRstPin);
    fscanf(f,"%s %s", key, server);
    pc.printf("Lecture de la config %s : %s\r\n", key, server);
    fclose(f);
}

/*******************************************************/
/**********************XBEE SEND************************/
/*******************************************************/

char frameID = 0;

inline char GetFrameID(){
    ++frameID;
    if (frameID == 0){
        frameID = 1;
    }
    return frameID;
}

void SetCheckSum(char * buffer){
    uint16_t length = GetFrameLength(buffer);
    
    char sum = 0;
    
    int max = length + 3;
    
    for(int i = 3; i < max; ++i){
        sum += buffer[i];
    }
    
    buffer[max] = 0xff - sum;
}

void XBeeSend(char * buffer, int count){
    for ( int i = 0; i < count; ++i ){
        xbee->putc(buffer[i]);
    }
}

void XBeeSendATCommand(bool queue, char * type, char * data, int dataLength){
    char buffer[128];
    buffer[START_IDX] = START;
    buffer[LENGTH_MSB_IDX] = (dataLength + AT_MIN_SIZE) >> 8;
    buffer[LENGTH_LSB_IDX] = (dataLength + AT_MIN_SIZE) & 0xff;
    buffer[API_ID_IDX] = queue ? API_ID_AT_CMD_QUEUE : API_ID_AT_CMD;
    buffer[FRAME_ID_IDX] = GetFrameID();
    memcpy(&buffer[AT_CMD_ID_IDX], type, AT_CMD_ID_SIZE);
    memcpy(&buffer[AT_PARAM_IDX], data, dataLength);
    
    SetCheckSum(buffer);
    
    while(true){
        XBeeSend(buffer, dataLength + AT_MIN_SIZE + FRAME_MIN_SIZE);
    
        Thread::signal_wait(RESPONSE_SIGNAL);
        
        switch (responseStatus){
        case AT_CMD_RSP_STATUS_OK:
            return;
        case AT_CMD_RSP_STATUS_ERROR:
        case AT_CMD_RSP_STATUS_INVALID_CMD:
        case AT_CMD_RSP_STATUS_INVALID_PARAM:
        case AT_CMD_RSP_STATUS_TX_FAILURE:
        default:
            pc.printf("This AT error occured : %02x\r\n", responseStatus);
            break;
        }
    }
}

inline void XBeeSendATID(){
    char idBuf[8];
    for (int i = 0; i < 8; ++i){
        idBuf[i] = (panID >> (56 - 8 * i)) & 0xff;
    }
    XBeeSendATCommand(true, "ID", idBuf, 8);
}

inline void XBeeSendATWR(){
    XBeeSendATCommand(true, "WR", nullptr, 0);
}

inline void XBeeSendATAC(){
    XBeeSendATCommand(true, "AC", nullptr, 0);
}

void XbeeSendRemoteAtCommand(long long int addr64, short addr16, char opt, char * type, char * data, int dataLength){
    char buffer[128];
    buffer[START_IDX] = START;
    buffer[LENGTH_MSB_IDX] = (dataLength + REMOTE_AT_RQST_MIN_SIZE) >> 8;
    buffer[LENGTH_LSB_IDX] = (dataLength + REMOTE_AT_RQST_MIN_SIZE) & 0xff;
    buffer[API_ID_IDX] = API_ID_REMOTE_AT_RQST;
    buffer[FRAME_ID_IDX] = GetFrameID();
    memcpy(&buffer[REMOTE_AT_RQST_64BIT_MSB_IDX], &addr64, ADDR_64BIT_SIZE);
    memcpy(&buffer[REMOTE_AT_RQST_16BIT_MSB_IDX], &addr16, ADDR_16BIT_SIZE);
    buffer[REMOTE_AT_RQST_OPT_IDX] = opt;
    memcpy(&buffer[REMOTE_AT_RQST_AT_CMD1_IDX], type, AT_CMD_ID_SIZE);
    memcpy(&buffer[REMOTE_AT_RQST_AT_PARAM_IDX], data, dataLength);
    
    SetCheckSum(buffer);
    
    while(true){
        XBeeSend(buffer, dataLength + REMOTE_AT_RQST_MIN_SIZE + FRAME_MIN_SIZE);
    
        Thread::signal_wait(RESPONSE_SIGNAL);
        
        switch (responseStatus){
        case REMOTE_AT_CMD_RSP_STATUS_OK:
            return;
        default:
            pc.printf("This AT error occured : %02x\r\n", responseStatus);
            break;
        }
    }
}

/*******************************************************/
/**********************XBEE READ************************/
/*******************************************************/

void HandleAtRemoteCommandResponse(char * cmd){
    responseStatus = cmd[REMOTE_CMD_RSP_STATUS_IDX];
    XBeeProducer->signal_set(RESPONSE_SIGNAL);
}

void HandleBtnPacket(char* cmd){
    ButtonEvent* evt = btnPool.alloc();
    memcpy(evt->id, BTN_ID, 3);
    evt->state = cmd[RECEIVED_PACKET_DATA_IDX + 3] == 0x01;
    event.put((void*)evt);
}

void HandleAccPacket(char* cmd){
    AccelerometerEvent* evt = accPool.alloc();
    memcpy(evt->id, ACC_ID, 3);
    memcpy(evt->x, &cmd[RECEIVED_PACKET_DATA_IDX + 3], 2);
    memcpy(evt->y, &cmd[RECEIVED_PACKET_DATA_IDX + 5], 2);
    memcpy(evt->z, &cmd[RECEIVED_PACKET_DATA_IDX + 7], 2);
    event.put((void*)evt);
}

void HandleXbeeReceivedPacket(char * cmd){
    if (rooterCount < ROOTER_MAX){
        Rooter r;
        r.addr64 = Get64Addr(cmd, RECEIVED_PACKET_64BIT_MSB_IDX);
        r.addr16 = Get16Addr(cmd, RECEIVED_PACKET_16BIT_MSB_IDX);
        
        bool found = false;
        for (int i = 0; i < rooterCount; ++i){
            if (rooters[i] == r){
                found = true;
                break;
            }
        }
        if (!found){
            rooterMutex.lock();
            rooters[rooterCount] = r;
            ++rooterCount;
            rooterMutex.unlock();
        }
    }
    
    if (cmd[RECEIVED_PACKET_DATA_IDX] == BTN_ID[0] && 
        cmd[RECEIVED_PACKET_DATA_IDX + 1] == BTN_ID[1] && 
        cmd[RECEIVED_PACKET_DATA_IDX + 2] == BTN_ID[2]){
        HandleBtnPacket(cmd);
    }
    
    if (cmd[RECEIVED_PACKET_DATA_IDX] == ACC_ID[0] && 
        cmd[RECEIVED_PACKET_DATA_IDX + 1] == ACC_ID[1] && 
        cmd[RECEIVED_PACKET_DATA_IDX + 2] == ACC_ID[2]){
        HandleAccPacket(cmd);
    }
}

void HandleXbeeModemStatus(char * cmd){
    switch(cmd[MODEM_STATUS_STATUS_IDX]){
    case MODEM_STATUS_HARDWARE_RST:
        XBeeProducer->signal_set(HARDWARE_RESET_SIGNAL);
        break;
    case MODEM_STATUS_COORDINATOR_STARTED:
        XBeeProducer->signal_set(COORDINATOR_STARTED_SIGNAL);
        break;
    default:
        pc.printf("Unhandled modem status received : %02x\r\n", cmd[MODEM_STATUS_STATUS_IDX]);
        break;
    }
}

void HandleXBeeATCommandResponse(char * cmd){
    responseStatus = cmd[AT_CMD_RSP_STATUS_IDX];
    XBeeProducer->signal_set(RESPONSE_SIGNAL);
}

void HandleXbeeReceivedCommand(char * cmd){
    switch(cmd[API_ID_IDX]){
    case API_ID_AT_CMD_RSP:
        HandleXBeeATCommandResponse(cmd);
        break;
    case API_ID_MODEM_STATUS:
        HandleXbeeModemStatus(cmd);
        break;
    case API_ID_RECEIVED_PACKET:
        HandleXbeeReceivedPacket(cmd);
        break;
    case API_ID_REMOTE_CMD_RSP:
        HandleAtRemoteCommandResponse(cmd);
        break;
    default:
        pc.printf("Unhandle XBee Command received : %02x\r\n", cmd[API_ID_IDX]);
    }
}

/*******************************************************/
/************************INIT***************************/
/*******************************************************/

bool InitXBee(){
    xbeeRst->write(0);
    wait(0.4);
    xbeeRst->write(1);
    
    Thread::signal_wait(HARDWARE_RESET_SIGNAL);
    
    XBeeSendATID();
    XBeeSendATWR();
    XBeeSendATAC();
    
    Thread::signal_wait(COORDINATOR_STARTED_SIGNAL);
     
    pc.printf("XBee configured\r\n");
    
    return true;
}

void ConsumerMain(){
    char buffer[128];
    while(true){
        while(!xbee->readable()){
            continue;
        }
        buffer[START_IDX] = xbee->getc();
        if (buffer[START_IDX] != START){
            pc.printf("Wrong start byte received : %02x\r\n", buffer[START_IDX]);
            continue;
        }
        buffer[LENGTH_MSB_IDX] = xbee->getc();
        buffer[LENGTH_LSB_IDX] = xbee->getc();
        int length = GetFrameLength(buffer);
        
        for (int i = 0; i <= length; ++i){
            buffer[i + API_ID_IDX] = xbee->getc();
        }
        if (!ValidateCheckSum(buffer)){
            pc.printf("Bad CheckSum : %02x\r\n", buffer[length + FRAME_MIN_SIZE - 1]);
            continue;
        }
        
        HandleXbeeReceivedCommand(buffer);
    }
}

void ToggleRemoteRooters(){
    rooterMutex.lock();
    for(int i = 0; i < rooterCount; ++i){
        
    }
    rooterMutex.unlock();
}

bool ProducerInit(){
    if (!InitXBee()){
        pc.printf("Connection problem with the XBee\r\n");
        return false;
    }
    
    return true;
}

void Tick(){
    XBeeProducer->signal_set(TICKER_SIGNAL);
}

void ProducerMain(const void*){
    if (!ProducerInit()){
        pc.printf("Initialization problem\r\n");
        return;
    }
    
    timer.attach(&Tick, 1);
    
    while(true){
        Thread::signal_wait(TICKER_SIGNAL);
        ToggleRemoteRooters();
    }
}

int main() {
    // Lecture de la configuration.
    ReadConfig();
    
    //Créer les interfaces de communication des capteurs avec les données de la config.
    Serial mainXbee(GetPinName(xbeeTxPin), GetPinName(xbeeRxPin));
    DigitalOut mainXbeeRst(GetPinName(xbeeRstPin));
    
    //Rendre les interfaces de communication globaux.
    xbee = &mainXbee;
    xbeeRst = &mainXbeeRst;
    
    Thread consumer(ConsumerMain);
    XBeeConsumer = &consumer;
    
    Thread producer(ProducerMain);
    XBeeProducer = &producer;
    
    // Mettre la thread principale dans un état de waiting à l'infinie
    Thread::signal_wait(0x1);
}