Working Thread (the wireless kind) example with DHCP Ethernet enabled. At this point, router is not a correct description. I do not know if Thread will handle routing automatically or I will need to do something to enable internet connectivity to a Thread client device. That is the goal, give a Thread client a routable connection to the internet.

Dependencies:   EthernetInterface fsl_phy_mcr20a fsl_smac mbed-rtos mbed

main.cpp

Committer:
jmulvain
Date:
2016-11-03
Revision:
29:241a264ebe8f
Parent:
27:1eb29717bfd9

File content as of revision 29:241a264ebe8f:

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

#include "Phy.h"
#include "SMAC_Interface.h"
#include "SMAC_Config.h"
#include "MemManager.h"
#include "circular_buffer.h"

//includes for project
#include "EthernetInterface.h"
//end new includes
char * const cu8FreescaleLogo[]= {
    "\f\r\n",
    "\n\r\n\r\n\r      #\n",
    "\r     ###\n",
    "\r    ###  *\n",
    "\r     #  ***\n",
    "\r       ***  #\n",
    "\r        *  ###\n",
    "\r          ###\n",
    "\r        *  #\n",
    "\r       ***\n",
    "\r      ***  #\n",
    "\r    #  *  ###\n",
    "\r   ###   ###\n",
    "\r  ###  *  #         F R E E S C A L E\n",
    "\r   #  ***\n",
    "\r     ***            S E M I C O N D U C T O R\n",
    "\r   #  *\n",
    "\r  ###               2 0 1 5\n",
    "\r ###\n",
    "\r  #           Wireless Uart Demo\r\n\n",
    NULL
};

#define gMcps_Cnf_EVENT_c        (1<<1)
#define gMcps_Ind_EVENT_c        (1<<2)
#define gMlme_EdCnf_EVENT_c      (1<<3)
#define gMlme_CcaCnf_EVENT_c     (1<<4)
#define gMlme_TimeoutInd_EVENT_c (1<<5)
#define gWUSelf_EVENT_c          (1<<6)

#define gDefaultBaudRate_UART_c 115200UL

Serial uart(USBTX, USBRX);
CircularBuffer uartBuf;

#ifdef VERBOSE
static bool_t bCCAFailed;
static bool_t bACKFailed;
#endif
uint32_t gTaskEventFlags;
static uint8_t gau8TxDataBuffer[gMaxSmacSDULength_c  + sizeof(rxPacket_t)];
txPacket_t *gAppTxPacket;
rxPacket_t *gAppRxPacket;
static txContextConfig_t txConfigContext;


void PrintMenu(char * const pu8Menu[])
{
    uint8_t u8Index = 0;
    while(pu8Menu[u8Index]) {
        uart.printf(pu8Menu[u8Index]);
        u8Index++;
    }
}


void InitProject(void);
void InitApp(void);

extern smacErrors_t smacToAppMlmeSap(smacToAppMlmeMessage_t* pMsg, instanceId_t instance);
extern smacErrors_t smacToAppMcpsSap(smacToAppDataMessage_t* pMsg, instanceId_t instance);

DigitalOut led1(LED_GREEN);
InterruptIn sw2(SW2);
uint32_t button_pressed;
Thread *thread2;
Thread *eventsThread;

void uartSetBaudRate(uint32_t b)
{
    uart.baud(b);
}

void sw2_press(void)
{
    thread2->signal_set(0x1);
}

void led_thread(void const *argument)
{
    while (true) {
        led1 = !led1;
        Thread::wait(200);
    }
}

void button_thread(void const *argument)
{
    while (true) {
        Thread::signal_wait(0x1);
        button_pressed++;
    }
}

void events_thread(void const *argument)
{
    uint8_t rcvd = 0, c = 0;

    while (true) {
        Thread::signal_wait(0x1);
        if(gMcps_Cnf_EVENT_c == (gTaskEventFlags & gMcps_Cnf_EVENT_c)) {
            //get back in RX
            MLMERXEnableRequest(gAppRxPacket, 0);
            //uart.printf("McpsDataCnf: Packet sent\r\n");

        }

        if(gMcps_Ind_EVENT_c == (gTaskEventFlags & gMcps_Ind_EVENT_c)) {
            rcvd = gAppRxPacket->smacPdu.smacPdu[0];

            //get back in RX
            //gAppRxPacket = (rxPacket_t*)MEM_BufferAlloc(gMaxSmacSDULength_c + sizeof(rxPacket_t));
            //gAppRxPacket->u8MaxDataLength = gMaxSmacSDULength_c;
            uart.printf("%c", rcvd);
            MLMERXEnableRequest(gAppRxPacket, 0);


        }

        if(gMlme_TimeoutInd_EVENT_c == (gTaskEventFlags & gMlme_TimeoutInd_EVENT_c)) {
            uart.printf("MlmeTimeoutInd: \r\n");
        }

        if(gMlme_EdCnf_EVENT_c == (gTaskEventFlags & gMlme_EdCnf_EVENT_c)) {
            uart.printf("EdCnf: \r\n");
        }

        if(gMlme_CcaCnf_EVENT_c == (gTaskEventFlags & gMlme_CcaCnf_EVENT_c)) {
            uart.printf("CcaCnf: \r\n");
        }

        if(gWUSelf_EVENT_c == (gTaskEventFlags & gWUSelf_EVENT_c)) {
            if (buffer_Ok_c == uartBuf.getFromBuffer(&c)) {
                gAppTxPacket->smacPdu.smacPdu[0] = c;
                gAppTxPacket->u8DataLength = 1;
                (void)MLMERXDisableRequest();
                (void)MCPSDataRequest(gAppTxPacket);
            }
        }

        gTaskEventFlags = 0;
    }
}

int main()
{
    // Intialize Ethernet connection
    EthernetInterface eth;
    wait(1);
    //eth.init("169.254.151.121", "255.255.0.0", "169.254.151.122");
    eth.init();
    eth.connect();


    
    MEM_Init();
    Thread thread(led_thread);
    thread2 = new Thread(button_thread);
    eventsThread = new Thread(events_thread);
    Phy_Init();
    InitSmac();

    uartSetBaudRate(gDefaultBaudRate_UART_c);

    //Tell SMAC who to call when it needs to pass a message to the application thread.
    Smac_RegisterSapHandlers((SMAC_APP_MCPS_SapHandler_t)smacToAppMcpsSap,(SMAC_APP_MLME_SapHandler_t)smacToAppMlmeSap,0);

    InitApp();

    PrintMenu(cu8FreescaleLogo);//splash screen
//show ip address which will indicate success or fail
    printf("Success. Connected!. Device IP Address is %s\r\n", eth.getIPAddress());

    button_pressed = 0;
    sw2.fall(&sw2_press);
    while (true)
    {
        if(uart.readable())
        {
            (void)uartBuf.addToBuffer(uart.getc());
        }
        if ( uartBuf.getCount() )
        {
            gTaskEventFlags |= gWUSelf_EVENT_c;
            eventsThread->signal_set(0x1);
        }
        Thread::yield();
    }
}

void InitApp()
{
    gAppTxPacket = (txPacket_t*)gau8TxDataBuffer;   //Map TX packet to buffer
    gAppRxPacket = (rxPacket_t*)MEM_BufferAlloc(gMaxSmacSDULength_c + sizeof(rxPacket_t));

    InitProject();

    SMACFillHeader(&(gAppTxPacket->smacHeader), gDefaultAddress_c);

    (void)MLMEPAOutputAdjust(gDefaultOutputPower_c);
    (void)MLMESetChannelRequest(gDefaultChannelNumber_c);
    (void)MLMEConfigureTxContext(&txConfigContext);
    //AppDelayTmr = TMR_AllocateTimer();
    gAppRxPacket->u8MaxDataLength = gMaxSmacSDULength_c;
    (void)MLMERXEnableRequest(gAppRxPacket, 0);
}

/* (Management) Sap handler for managing timeout indication and ED confirm
   This is running in INTERRUPT context, so need to send messages to one of the task */
smacErrors_t smacToAppMlmeSap(smacToAppMlmeMessage_t* pMsg, instanceId_t instance)
{
    switch(pMsg->msgType) {
        case gMlmeEdCnf_c:
            gTaskEventFlags |= gMlme_EdCnf_EVENT_c;
            break;
        case gMlmeCcaCnf_c:
            gTaskEventFlags |= gMlme_CcaCnf_EVENT_c;
            break;
        case gMlmeTimeoutInd_c:
            gTaskEventFlags |= gMlme_TimeoutInd_EVENT_c;
            break;
        default:
            break;
    }
    eventsThread->signal_set(0x1);
    MEM_BufferFree(pMsg);
    return gErrorNoError_c;
}

/* (Data) Sap handler for managing data confirm and data indication
   This is running in INTERRUPT context, so need to send messages to one of the task */
smacErrors_t smacToAppMcpsSap(smacToAppDataMessage_t* pMsg, instanceId_t instance)
{
    switch(pMsg->msgType) {
        case gMcpsDataInd_c:
            if(pMsg->msgData.dataInd.pRxPacket->rxStatus == rxSuccessStatus_c) {
                gTaskEventFlags |= gMcps_Ind_EVENT_c;
            }
            break;

        case gMcpsDataCnf_c:
#ifdef VERBOSE
            if(pMsg->msgData.dataCnf.status == gErrorChannelBusy_c) {
                bCCAFailed = TRUE;
            }

            if(pMsg->msgData.dataCnf.status == gErrorNoAck_c) {
                bACKFailed = TRUE;
            }
#endif

            gTaskEventFlags |= gMcps_Cnf_EVENT_c;
            break;

        default:
            break;
    }
    eventsThread->signal_set(0x1);
    MEM_BufferFree(pMsg);

    return gErrorNoError_c;
}

void InitProject(void)
{
    /*Global Data init*/
#ifdef VERBOSE
    bACKFailed                        = FALSE;
    bCCAFailed                        = FALSE;
#endif

    gTaskEventFlags = 0;

    txConfigContext.autoAck           = FALSE;
    txConfigContext.ccaBeforeTx       = FALSE;
    txConfigContext.retryCountAckFail = 0;
    txConfigContext.retryCountCCAFail = 0;
}