This program utilizes the mcr20 Thread Shield on the FRDM-K64F MCU which is a two-part workspace (HVAC Server (RX)/Probe(TX)) to handle low temperature events read at the probe(s) to prevent pipes from freezing.

Dependencies:   DHT fsl_phy_mcr20a fsl_smac mbed-rtos mbed

Fork of mcr20_wireless_uart by NXP

main.cpp

Committer:
haircules
Date:
2017-03-30
Revision:
29:c49f83ab80bd
Parent:
27:1eb29717bfd9

File content as of revision 29:c49f83ab80bd:

#include "mbed.h"
#include "rtos.h"
#include "DHT.h"
#include "Phy.h"
#include "SMAC_Interface.h"
#include "SMAC_Config.h"
#include "MemManager.h"
#include "circular_buffer.h"

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

#define BUF_SIZE 3

Serial uart(USBTX, USBRX);
CircularBuffer uartBuf;
DHT tempSensor(D4,DHT22);

#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);
DigitalOut led2(LED_RED);
DigitalOut led3(LED_BLUE);
InterruptIn sw2(SW2);
uint32_t button_pressed;
uint8_t timer;
Thread *thread2;
Thread *eventsThread;
Thread *timerThread;

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

/*ISR for sw2*/
/*On sw2 press, spoof HVAC server by sending 30F as current temp*/
void sw2_press(void)
{      
	/*Add fake temp to buffer*/ 
    (void)uartBuf.addToBuffer('0');
    (void)uartBuf.addToBuffer('3');
    (void)uartBuf.addToBuffer('0');
    
    /*Set flags for TX in eventsThread and signal that an event has occured*/
    gTaskEventFlags |= gWUSelf_EVENT_c;
    thread2->signal_set(0x1);
    
}

void timer_thread(void const *argument)
{
	char Buffer[BUF_SIZE];
	int temp = 0;
	int error = 0;
	
	while (true) {
	
		Thread::wait(1000);
		timer++;	
		
		printf("timer(%d)\n\r",timer);
		
		/*Update temp and load to Buffer every 10 seconds*/
		if(timer >= 10)
		{
			printf("Timer up! Preparing to send temp..\n\r");
			
			/*Reset timer*/
			timer = 0;
			
			/*Wait for tempSensor data to be ready*/
        	error = tempSensor.readData();
        	while(0 != error)
        	{
        		error = tempSensor.readData();
        	}
        	
        	temp = (int)tempSensor.ReadTemperature(FARENHEIT);
        	
        	/*Convert temp to ASCII and add to Buffer*/
        	Buffer[0] = (temp / 100) + 0x30;//hundreds digit
        	Buffer[1] = ((temp % 100) / 10) + 0x30;//tens digit
        	Buffer[2] = ((temp % 100) % 10) + 0x30;//ones digit
        		
        	/*Buffer gets ASCII conversion of temp*/
        	for(int i = 0; i < sizeof(Buffer); i++)
        	{
        		(void)uartBuf.addToBuffer(Buffer[i]);
        	}/*end for*/
		}/*end if*/	
	}/*end while*/
}

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)
    {
        /*Wait for signal*/
        Thread::signal_wait(0x1);
        
        /*If packet has been sent, reenable recieving mode*/
        if(gMcps_Cnf_EVENT_c == (gTaskEventFlags & gMcps_Cnf_EVENT_c))
        {
            /*Reenable RX requests*/
            MLMERXEnableRequest(gAppRxPacket, 0); 

        }
        
        /*If a packet has been recieved, rcvd gets data*/
        if(gMcps_Ind_EVENT_c == (gTaskEventFlags & gMcps_Ind_EVENT_c))
        {
            for(int i = 0; i <= gAppRxPacket->u8DataLength; i++)
            {
            	rcvd = gAppRxPacket->smacPdu.smacPdu[i];
				uart.printf("%c", rcvd);
			}
			
            /*Reenable RX requests*/
            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 there is something on the buffer, load packet and send*/
        if(gWUSelf_EVENT_c == (gTaskEventFlags & gWUSelf_EVENT_c))
        {
            
            /*Set Data Length to number of items on uartBuf*/
            gAppTxPacket->u8DataLength = uartBuf.getCount();
                
            /*Load TX packets until uartBuf is empty*/
            for(int i = 0; uartBuf.getCount() > 0; i++)
            {
            	uartBuf.getFromBuffer(&c);
        		gAppTxPacket->smacPdu.smacPdu[i] = c;
 			}
 				/*Disable RX requests (block incoming packets)*/
                (void)MLMERXDisableRequest();
                /*Generate request to send data packet*/
                (void)MCPSDataRequest(gAppTxPacket);
                
                printf("Data Sent\n\r");
                
                /*Toggle Red LED after transmission*/
                led2 = !led2;
            
        }
       
        gTaskEventFlags = 0;
    }
}

int main()
{    
    led1 = 1;/*Turn off Green LED*/
    led2 = 1;/*Turn off Red LED*/
    led3 = 1;/*Turn off Blue LED*/
    
    MEM_Init();
    Thread thread(led_thread);
    thread2 = new Thread(button_thread);
    eventsThread = new Thread(events_thread);
    timerThread = new Thread(timer_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);
	    
    button_pressed = 0;
    sw2.fall(&sw2_press);
    while (true) 
    {
        /*Set signal for eventsThread if anything on uartBuf to be sent*/
        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;
}