/* $Id: device.c,v 1.15 2006/11/28 09:44:29 awachtle Exp $ */ /*--------------------------------------------------------------------------- PROPRIETARY INFORMATION OF ATMEL CORPORATION Copyright (c) 2006 Atmel Corporation The scope of use of the material contained herein is limited strictly to the terms of the LICENSE which grants permission for the use of the material. Distribution of this material and all copies thereof to any entity other than to the EMPLOYEES of the Licensee, as the term is defined in the LICENSE, is strictly forbidden without a prior written consent of Atmel Corporation. ---------------------------------------------------------------------------- */ /* === Includes ============================================================ */ #include #include #if defined (__GNUC__) # include #elif defined(__ICCAVR__) # include # include # include # define sei() __enable_interrupt() # define _BV(x) (1<<(x)) #endif #include "wpan_defines.h" #include "ieee_const.h" #include "wpan_mac.h" /* === Macros ============================================================== */ #ifndef RF_CHANNEL # define RF_CHANNEL (18) # warning "RF channel undefined, setting to 18" #endif #define ALL_HIGH_BAND_CHANNELS ((uint32_t)0x07FFF800) #define CHANNELMASK(a) (1UL<<(a)) #define SCAN_DURATION (3) /* scan for 3 * symbol period = 48 µs */ /* macro stores the state value and sets the state led to 0 */ #define SET_STATE(x) do { d_status.state=(x); \ PORTE |= (_BV((uint8_t)(x)));} while(0) /* === Typedefs ============================================================ */ typedef enum { INIT_DONE, PEND_RESET, PEND_SCAN, PEND_ASSOCIATE, PEND_SET_SHORT_ADDR, PEND_START, RUN, } device_state_t; typedef struct { bool led; bool switch_pressed; uint16_t device_short_address; uint8_t coord_address_mode; uint64_t coord_address; uint16_t pan_id; uint8_t logical_channel; uint8_t msdu_handle; device_state_t state; } device_status_t; /* === Static Variables ==================================================== */ static device_status_t d_status; /* === Prototypes ========================================================== */ static void application_init(void); static void switch_task(void); void mac_do_reset(void); static void mac_scan(void); static void mac_associate(void); /* === Implementation ====================================================== */ int main(void) { application_init(); mac_do_reset(); while(1) { while(wpan_task()) { /* only short running tasks are called here */ } /* main user task */ switch_task(); } } static void application_init(void) { /* reset global application status variable */ memset(&d_status, 0, sizeof(d_status)); /* init IO ports */ DDRE = 0xFF; /* all bits of PORT E are outputs */ PORTE = 0x00; /* switch all leds ON (inverse logic) */ DDRF &= 0xF0; /* lower bits of PORT F are inputs */ /* init mac layer */ wpan_init(); SET_STATE(INIT_DONE); /* enable interrupts */ sei(); return; } static void switch_task(void) { if (d_status.state == RUN) { bool send_data = false; if (!d_status.switch_pressed) { /* check if button is pressed. */ if ((PINF & 0x01) == 0x00) { d_status.switch_pressed = true; d_status.led = !d_status.led; send_data = true; } } else { /* check if button is released. */ if ((PINF & 0x01) == 0x01) { d_status.switch_pressed = false; } } if (send_data) { /* send data */ wpan_mcpsdata_addr_t addr_info; addr_info.SrcAddrMode = WPAN_ADDRMODE_SHORT; addr_info.SrcPANId = d_status.pan_id; addr_info.SrcAddr = d_status.device_short_address; addr_info.DstAddrMode = d_status.coord_address_mode; addr_info.DstPANId = d_status.pan_id; addr_info.DstAddr = d_status.coord_address; wpan_mcps_data_request(&addr_info, d_status.msdu_handle++, WPAN_TXOPT_ACK, (void *)&d_status.led, sizeof(uint8_t)); } } return; } void mac_do_reset() { wpan_mlme_reset_request( true ); SET_STATE( PEND_RESET ); } void usr_mlme_reset_conf (uint8_t status) { if ((status == MAC_SUCCESS) && (d_status.state == PEND_RESET)) { mac_scan(); } return; } static void mac_scan(void) { uint32_t chanmsk; chanmsk = CHANNELMASK(RF_CHANNEL); wpan_mlme_scan_request(MLME_SCAN_TYPE_ACTIVE, chanmsk, SCAN_DURATION); SET_STATE( PEND_SCAN ); return; } void usr_mlme_scan_conf(uint8_t status, uint8_t ScanType, uint32_t UnscannedChannels, uint8_t ResultListSize, uint8_t *data, uint8_t data_length) { bool scan_success = false; if ((status == MAC_SUCCESS) && (d_status.state == PEND_SCAN)) { /* there should only be one PAN descriptor */ if (ResultListSize == 1) { scan_success = true; wpan_pandescriptor_t *pandesc = (wpan_pandescriptor_t *)data; /* save information from the PAN Descriptor */ d_status.coord_address_mode = pandesc->CoordAddrMode; d_status.coord_address = pandesc->CoordAddress; d_status.pan_id = pandesc->CoordPANId; d_status.logical_channel = pandesc->LogicalChannel; /* associate to the PAN coordinator */ mac_associate(); } } if (!scan_success) { /* no success, scan again */ mac_scan(); } return; } static void mac_associate(void) { uint8_t capability_info; capability_info = WPAN_CAP_FFD | WPAN_CAP_PWRSOURCE |\ WPAN_CAP_RXONWHENIDLE | WPAN_CAP_ALLOCADDRESS; wpan_mlme_associate_request(d_status.logical_channel, d_status.coord_address_mode, d_status.pan_id, d_status.coord_address, capability_info, false); SET_STATE( PEND_ASSOCIATE ); return; } void usr_mlme_associate_conf ( uint16_t AssocShortAddress, uint8_t status) { if ((status == MAC_SUCCESS) && (d_status.state == PEND_ASSOCIATE)) { /* save the device short address */ d_status.device_short_address = AssocShortAddress; /* mark that association is complete */ SET_STATE( RUN ); /* turn all LEDs off after successfull association */ PORTE = 0xFF; } else { /* somethig went wrong, try association again */ mac_associate(); } return; } void usr_mcps_data_ind(wpan_mcpsdata_addr_t *pAddrInfo, uint8_t mpduLinkQuality, uint8_t SecurityUse, uint8_t ACLEntry, uint8_t msduLength, uint8_t *msdu) { if ((d_status.state == RUN) && (pAddrInfo->DstPANId == d_status.pan_id)) { /* Data packet contains LED information. */ PORTE = ~((uint8_t)*msdu); } }