/** * \file task.c * * \brief Implementation of Tasks for Demo Application on MiWi P2P * * Copyright (c) 2018 - 2019 Microchip Technology Inc. and its subsidiaries. * * \asf_license_start * * \page License * * Subject to your compliance with these terms, you may use Microchip * software and any derivatives exclusively with Microchip products. * It is your responsibility to comply with third party license terms applicable * to your use of third party software (including open source software) that * may accompany Microchip software. * * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. * * \asf_license_stop * */ /* * Support and FAQ: visit Microchip Support */ /***********************Headers***************************************/ #include "task.h" #include "miwi_api.h" #include "p2p_demo.h" #include "asf.h" #if defined(ENABLE_NETWORK_FREEZER) #include "pdsDataServer.h" #include "wlPdsTaskManager.h" #endif #if defined(ENABLE_SLEEP_FEATURE) #include "sleep_mgr.h" #endif #include "phy.h" /************************** VARIABLES ************************************/ #define LIGHT 0x01 #define SWITCH 0x02 /*************************************************************************/ // AdditionalNodeID variable array defines the additional // information to identify a device on a PAN. This array // will be transmitted when initiate the connection between // the two devices. This variable array will be stored in // the Connection Entry structure of the partner device. The // size of this array is ADDITIONAL_NODE_ID_SIZE, defined in // miwi_config.h. // In this demo, this variable array is set to be empty. /*************************************************************************/ #if ADDITIONAL_NODE_ID_SIZE > 0 uint8_t AdditionalNodeID[ADDITIONAL_NODE_ID_SIZE] = {LIGHT}; #endif /* Connection Table Memory */ CONNECTION_ENTRY connectionTable[CONNECTION_SIZE]; #ifdef ENABLE_ACTIVE_SCAN /* Active Scan Results Table Memory */ ACTIVE_SCAN_RESULT activeScanResults[ACTIVE_SCAN_RESULT_SIZE]; #endif defaultParametersRomOrRam_t defaultParamsRomOrRam = { .ConnectionTable = &connectionTable[0], #ifdef ENABLE_ACTIVE_SCAN .ActiveScanResults = &activeScanResults[0], #endif #if ADDITIONAL_NODE_ID_SIZE > 0 .AdditionalNodeID = &AdditionalNodeID[0], #endif .networkFreezerRestore = 0, }; defaultParametersRamOnly_t defaultParamsRamOnly = { .dummy = 0, }; extern API_UINT16_UNION myPANID; /*************************************************************************/ // The variable myChannel defines the channel that the device // is operate on. This variable will be only effective if energy scan // (ENABLE_ED_SCAN) is not turned on. Once the energy scan is turned // on, the operating channel will be one of the channels available with // least amount of energy (or noise). /*************************************************************************/ #if defined(PHY_AT86RF233) uint8_t myChannel = 26; /* Range: 11 to 26 */ #elif defined(PHY_AT86RF212B) uint8_t myChannel = 8; /* Range for default configuration: 1 to 10 Note: TX Power and PHY Mode Setting needs to be modified as per the recommendation from Data Sheet for European band (ie.,Channel 0)*/ #endif /********************************************************************* * Function: bool freezer_feature(void) * * Overview: Allows user to select network freezer restore * * Return: true if network freezer to be used for restoring ********************************************************************/ bool freezer_feature(void) { MIWI_TICK tick1, tick2; uint8_t switch_val; tick1.Val = MiWi_TickGet(); while(1) { tick2.Val = MiWi_TickGet(); if(MiWi_TickGetDiff(tick2, tick1) > (ONE_SECOND * 4)) break; switch_val = ButtonPressed (); if(switch_val == 1) { #if defined (ENABLE_LCD) LCDDisplay((char *)"Restoring Network !!", 0, false); delay_ms(1000); #endif return true; } else { return false; } } return false; } /********************************************************************* * Function: static void longAddressValidationAndUpdation(void) * * Overview: validates the long address and assigns new address by random allocation if invalid address found ********************************************************************/ static void longAddressValidationAndUpdation(void) { bool invalidIEEEAddrFlag = false; uint64_t invalidIEEEAddr; srand(PHY_RandomReq()); /* Check if a valid IEEE address is available. 0x0000000000000000 and 0xFFFFFFFFFFFFFFFF is persumed to be invalid */ /* Check if IEEE address is 0x0000000000000000 */ memset((uint8_t *)&invalidIEEEAddr, 0x00, LONG_ADDR_LEN); if (0 == memcmp((uint8_t *)&invalidIEEEAddr, (uint8_t *)&myLongAddress, LONG_ADDR_LEN)) { invalidIEEEAddrFlag = true; } /* Check if IEEE address is 0xFFFFFFFFFFFFFFFF */ memset((uint8_t *)&invalidIEEEAddr, 0xFF, LONG_ADDR_LEN); if (0 == memcmp((uint8_t *)&invalidIEEEAddr, (uint8_t *)&myLongAddress, LONG_ADDR_LEN)) { invalidIEEEAddrFlag = true; } if (invalidIEEEAddrFlag) { /* In case no valid IEEE address is available, a random * IEEE address will be generated to be able to run the * applications for demonstration purposes. * In production code this can be omitted. */ uint8_t* peui64 = (uint8_t *)&myLongAddress; for(uint8_t i = 0; i < MY_ADDRESS_LENGTH; i++) { *peui64++ = (uint8_t)rand(); } } /* Set the address in transceiver */ PHY_SetIEEEAddr((uint8_t *)&myLongAddress); } bool startNetwork = false; /********************************************************************* * Function: static void Connection_Confirm(miwi_status_t status) * * Overview: callback function called upon MiAPP_StarConnection * or MiApp_EstablishConnection procedure completes * Parameter: status of the completed operation ********************************************************************/ static void Connection_Confirm(miwi_status_t status) { /* If success or already exists status, update the LED,CONSOLE,LCD and show the demo instruction for the user to proceed */ if ((SUCCESS == status) || (ALREADY_EXISTS == status)) { #if !defined(ENABLE_SLEEP_FEATURE) /* Turn on LED 1 to indicate connection established */ LED_On(LED1); #endif if (!startNetwork) { DemoOutput_Channel(myChannel, 1); } else { printf("\r\nStarted Wireless Communication on Channel "); printf("%u",currentChannel); printf("\r\n"); } DemoOutput_Instruction(); #if defined(ENABLE_CONSOLE) DumpConnection(0xFF); #endif } else { /* Upon EstablishConnection failure, initiate the startConnection to form a network */ startNetwork = true; MiApp_StartConnection(START_CONN_DIRECT, 10, (1L << myChannel), Connection_Confirm); } } /********************************************************************* * Function: bool Initialize_Demo(bool freezer_enable) * * Overview: Initializes the demo by initializing protocol, required components and initiates connection ********************************************************************/ bool Initialize_Demo(bool freezer_enable) { uint16_t broadcastAddr = 0xFFFF; /* Subscribe for data indication */ MiApp_SubscribeDataIndicationCallback(ReceivedDataIndication); #ifdef ENABLE_SLEEP_FEATURE /* Sleep manager initialization */ sleepMgr_init(); #endif /* Update NetworkFreezerRestore parameter whether to restore from network freezer or not */ defaultParamsRomOrRam.networkFreezerRestore = freezer_enable; /* Initialize the P2P and Star Protocol */ if (MiApp_ProtocolInit(&defaultParamsRomOrRam, &defaultParamsRamOnly) == RECONNECTED) { printf("\r\nPANID:"); printf("%x",myPANID.v[1]); printf("%x",myPANID.v[0]); printf(" Channel:"); printf("%d",currentChannel); #if defined(PROTOCOL_P2P) DemoOutput_Instruction(); #else STAR_DEMO_OPTIONS_MESSAGE (role); #endif return true; } /* Unable to boot from the Network Freezer parameters, so initiate connection */ /* Check Valid address is found , else update with random */ longAddressValidationAndUpdation(); /* Enable all kinds of connection */ MiApp_ConnectionMode(ENABLE_ALL_CONN); // Set default channel if( MiApp_Set(CHANNEL, &myChannel) == false ) { DemoOutput_ChannelError(myChannel); return false; } DemoOutput_Channel(myChannel, 0); startNetwork = false; /* Try to establish a new connection with peer device by broadcast Connection Request */ return MiApp_EstablishConnection(myChannel, 2, (uint8_t*)&broadcastAddr, 0, Connection_Confirm); } /********************************************************************* * Function: void Run_Demo(void) * * Overview: runs the demo based on user input ********************************************************************/ void Run_Demo(void) { P2PTasks(); #if defined(ENABLE_NETWORK_FREEZER) #if PDS_ENABLE_WEAR_LEVELING PDS_TaskHandler(); #endif #endif run_p2p_demo(); } #ifdef ENABLE_CONSOLE #ifdef ENABLE_DUMP /********************************************************************* * void DumpConnection(uint8_t index) * * Overview: This function prints out the content of the connection * with the input index of the P2P Connection Entry * * PreCondition: * * Input: * index - The index of the P2P Connection Entry to be printed out * * Output: None * * Side Effects: The content of the connection pointed by the index * of the P2P Connection Entry will be printed out * ********************************************************************/ void DumpConnection(INPUT uint8_t index) { uint8_t i, j; if( index > CONNECTION_SIZE ) { printf("\r\n\r\nMy Address: 0x"); for(i = 0; i < MY_ADDRESS_LENGTH; i++) { printf("%02x",myLongAddress[MY_ADDRESS_LENGTH-1-i]); } #if defined(IEEE_802_15_4) printf(" PANID: 0x"); printf("%x",myPANID.v[1]); printf("%x",myPANID.v[0]); #endif printf(" Channel: "); printf("%d",currentChannel); } if( index < CONNECTION_SIZE ) { printf("\r\nConnection \tPeerLongAddress \tPeerInfo\r\n"); if( connectionTable[index].status.bits.isValid ) { printf("%02x",index); printf("\t\t\t"); for(i = 0; i < 8; i++) { if(i < MY_ADDRESS_LENGTH) { printf("%02x", connectionTable[index].Address[MY_ADDRESS_LENGTH-1-i] ); } else { printf("\t"); } } printf("/t"); #if ADDITIONAL_NODE_ID_SIZE > 0 for(i = 0; i < ADDITIONAL_NODE_ID_SIZE; i++) { printf("%02x", connectionTable[index].PeerInfo[i] ); } #endif printf("\r\n"); } } else { printf("\r\n\r\nConnection PeerLongAddress PeerInfo\r\n"); for(i = 0; i < CONNECTION_SIZE; i++) { if( connectionTable[i].status.bits.isValid ) { printf("%02x",i); printf(" "); for(j = 0; j < 8; j++) { if( j < MY_ADDRESS_LENGTH ) { printf("%02x", connectionTable[i].Address[MY_ADDRESS_LENGTH-1-j] ); } else { printf(" "); } } printf(" "); #if ADDITIONAL_NODE_ID_SIZE > 0 for(j = 0; j < ADDITIONAL_NODE_ID_SIZE; j++) { printf("%02x", connectionTable[i].PeerInfo[j] ); } #endif printf("\r\n"); } } } } #endif #endif