CC3000 test App

Dependencies:   CC3000HostDriver mbed

cc3000.cpp

Committer:
dflet
Date:
2013-09-14
Revision:
2:17c37c0b0534
Parent:
0:305844973572

File content as of revision 2:17c37c0b0534:

/*****************************************************************************
*
*  cc3000.c - CC3000 Functions Implementation
*  Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*    Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
*
*    Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the   
*    distribution.
*
*    Neither the name of Texas Instruments Incorporated nor the names of
*    its contributors may be used to endorse or promote products derived
*    from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/

#include "mbed.h"
#include "cc3000.h"
//#include <msp430.h>
#include "wlan.h" 
#include "evnt_handler.h"    // callback function declaration
#include "nvmem.h"
#include "socket.h"
//#include "common.h"
#include "netapp.h"
//#include "common.h"

//#include "demo_config.h"
#include "spi.h"
//#include "board.h"
//#include "dispatcher.h"
#include "spi_version.h"
//#include "application_version.h"
//#include "host_driver_version.h"
#include "security.h"
#include "CC3000TestApp.h"
#include "CC3000Core.h"
#include "DigitalClass.h"


char CheckSocket = 0;
// Smart Config Prefix - Texas Instruments
char aucCC3000_prefix[3] = {'T', 'T', 'T'};

signed char sd[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0};

const unsigned char smartconfigkey[] = {0x73,0x6d,0x61,0x72,0x74,0x63,0x6f,0x6e,0x66,0x69,0x67,0x41,0x45,0x53,0x31,0x36};

//const unsigned char pucUARTExampleAppString[] = {'\f', '\r','E', 'x', 'a', 'm', 'p', 'l', 'e', ' ', 'A', 'p', 'p', ':', 'd', 'r', 'i', 'v', 'e', 'r', ' ', 'v', 'e', 'r', 's', 'i', 'o', 'n', ' ' };
unsigned char pucIP_Addr[4];
unsigned char pucIP_DefaultGWAddr[4];
unsigned char pucSubnetMask[4];
unsigned char pucDNS[4];
char digits[100];
char cc3000state = CC3000_UNINIT;

tNetappIpconfigRetArgs ipinfo;

// Variable to indicate whether the Smart Config Process has finished
volatile unsigned long ulSmartConfigFinished = 0;

//*****************************************************************************
//
//! ConnectUsingSSID
//!
//! \param  ssidName is a string of the AP's SSID
//!
//! \return none
//!
//! \brief  Connect to an Access Point using the specified SSID
//
//*****************************************************************************
int ConnectUsingSSID(char * ssidName)
{
                    
    unsetCC3000MachineState(CC3000_ASSOC);
    
    // Disable Profiles and Fast Connect
    wlan_ioctl_set_connection_policy(0, 0, 0);
    
    wlan_disconnect();
    
    //__delay_cycles(10000);
    wait_us(500);
    
    // This triggers the CC3000 to connect to specific AP with certain parameters
    //sends a request to connect (does not necessarily connect - callback checks that for me)
#ifndef CC3000_TINY_DRIVER
    wlan_connect(0, ssidName, strlen(ssidName), NULL, NULL, 0);   
#else
    wlan_connect(ssidName, strlen(ssidName));
#endif
    // We don't wait for connection. This is handled somewhere else (in the main
    // loop for example).
    
    return 0;      
}


//*****************************************************************************
//
//! itoa
//!
//! @param[in]  integer number to convert
//!
//! @param[in/out]  output string
//!
//! @return number of ASCII parameters
//!
//! @brief  Convert integer to ASCII in decimal base
//
//*****************************************************************************
unsigned short itoa(char cNum, char *cString)
{
    char* ptr;
    char uTemp = cNum;
    unsigned short length;
    
    
    // value 0 is a special case
    if (cNum == 0)
    {
        length = 1;
        *cString = '0';
        
        return length;
    }
    
    // Find out the length of the number, in decimal base
    length = 0;
    while (uTemp > 0)
    {
        uTemp /= 10;
        length++;
    }
    
    // Do the actual formatting, right to left
    uTemp = cNum;
    ptr = cString + length;
    while (uTemp > 0)
    {
        --ptr;
        *ptr = digits[uTemp % 10];
        uTemp /= 10;
    }
    
    return length;
}


//*****************************************************************************
//
//! sendDriverPatch
//!
//! \param  pointer to the length
//!
//! \return none
//!
//! \brief  The function returns a pointer to the driver patch: since there is no patch yet - 
//!                it returns 0
//
//*****************************************************************************
char *sendDriverPatch(unsigned long *Length)
{
    *Length = 0;
    return NULL;
}


//*****************************************************************************
//
//! sendBootLoaderPatch
//!
//! \param  pointer to the length
//!
//! \return none
//!
//! \brief  The function returns a pointer to the boot loader patch: since there is no patch yet -
//!                it returns 0
//
//*****************************************************************************
char *sendBootLoaderPatch(unsigned long *Length)
{
    *Length = 0;
    return NULL;
}

//*****************************************************************************
//
//! sendWLFWPatch
//!
//! \param  pointer to the length
//!
//! \return none
//!
//! \brief  The function returns a pointer to the FW patch: since there is no patch yet - it returns 0
//
//*****************************************************************************

char *sendWLFWPatch(unsigned long *Length)
{
    *Length = 0;
    return NULL;
}


//*****************************************************************************
//
//! CC3000_UsynchCallback
//!
//! \param  Event type
//!
//! \return none
//!
//! \brief  The function handles asynchronous events that come from CC3000 device 
//!          and operates a LED4 to have an on-board indication
//
//*****************************************************************************

void CC3000_UsynchCallback(long lEventType, char * data, unsigned char length)
{
    if (lEventType == HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE)
    {
        ulSmartConfigFinished = 1;      
    }
    
    if (lEventType == HCI_EVNT_WLAN_UNSOL_INIT)
    {
        setCC3000MachineState(CC3000_INIT);
    }
    if (lEventType == HCI_EVNT_WLAN_UNSOL_CONNECT)
    {
              ulCC3000Connected = 1;
        setCC3000MachineState(CC3000_ASSOC);
        
    }
    
    if (lEventType == HCI_EVNT_WLAN_UNSOL_DISCONNECT)
    {
        ulCC3000Connected = 0;
        //restartMSP430();
        unsetCC3000MachineState(CC3000_ASSOC);
        
    }
    if (lEventType == HCI_EVNT_WLAN_UNSOL_DHCP)
    {
        setCC3000MachineState(CC3000_IP_ALLOC);        
    }
    
    // This Event is gengerated when the TCP connection is Half closed
    if (lEventType == HCI_EVNT_BSD_TCP_CLOSE_WAIT)
    {
      sd[data[0]] = 1;
      CheckSocket = 1;
    }
}

//*****************************************************************************
//
//! initDriver
//!
//!  \param  None
//!
//!  \return none
//!
//!  \brief  The function initializes a CC3000 device and triggers it to start operation
//
//*****************************************************************************
int
  initDriver(void)
{
        // Init GPIO's
    //pio_init();
    DigitalClass pio(p9, p10);
    // Init SPI
    init_spi();
    
    //DispatcherUARTConfigure();
    
    // Globally enable interrupts
    //__enable_interrupt();
    //  __enable_irq();  
    //
    // WLAN On API Implementation
    //
    wlan_init( CC3000_AsynchCallback, sendWLFWPatch, sendDriverPatch, sendBootLoaderPatch, ReadWlanInterruptPin, WlanInterruptEnable, WlanInterruptDisable, WriteWlanPin);
    
    //
    // Trigger a WLAN device
    //
    wlan_start(0);
    
    //
    // Mask out all non-required events from CC3000
    //

    wlan_set_event_mask(HCI_EVNT_WLAN_KEEPALIVE|HCI_EVNT_WLAN_ASYNC_PING_REPORT|HCI_EVNT_WLAN_UNSOL_INIT);

    // Generate event to CLI: send a version string
    char cc3000IP[50];
    char *ccPtr;
    unsigned short ccLen;
        
    //DispatcherUartSendPacket((const char*)pucUARTExampleAppString, sizeof(pucUARTExampleAppString));
        
    ccPtr = &cc3000IP[0];
    ccLen = itoa(PALTFORM_VERSION, ccPtr);
    ccPtr += ccLen;
    *ccPtr++ = '.';
    //ccLen = itoa(APPLICATION_VERSION, ccPtr);
    ccPtr += ccLen;
    *ccPtr++ = '.';
    ccLen = itoa(SPI_VERSION_NUMBER, ccPtr);
    ccPtr += ccLen;
    *ccPtr++ = '.';
    //ccLen = itoa(DRIVER_VERSION_NUMBER, ccPtr);
    ccPtr += ccLen;
    *ccPtr++ = '\r';
        *ccPtr++ = '\n';
    *ccPtr++ = '\0';
        ccLen = strlen(cc3000IP);
        
    //DispatcherUartSendPacket((const char*)cc3000IP, strlen(cc3000IP));
    
    // CC3000 has been initialized
    setCC3000MachineState(CC3000_INIT);
    
    unsigned long aucDHCP, aucARP, aucKeepalive, aucInactivity;
    
    aucDHCP = 14400;
    aucARP = 3600;      
    aucKeepalive = 10;
    aucInactivity = 50;
    
    if(netapp_timeout_values(&(aucDHCP), &(aucARP), &(aucKeepalive), &(aucInactivity)) != 0)
    {
      while(1);
    }
    
    return(0);
}


//*****************************************************************************
//
//!  \brief  Return the highest state which we're in
//!
//!  \param  None
//!
//!  \return none
//!
//
//*****************************************************************************
char highestCC3000State()
{
    // We start at the highest state and go down, checking if the state
    // is set.
    char mask = 0x80;
    while(!(cc3000state & mask))
    {
        mask = mask >> 1;
    }
        
    return mask;
}

//*****************************************************************************
//
//!  \brief  Return the current state bits
//!
//!  \param  None
//!
//!  \return none
//!
//
//*****************************************************************************
char currentCC3000State()
{
    return cc3000state;
}

void setCC3000MachineState(char stat)
{        
    char bitmask = stat;
    cc3000state |= bitmask;
    
    int i = FIRST_STATE_LED_NUM;
    
    // Find LED number which needs to be set
    while(bitmask < 0x80)
    {      
        bitmask  = bitmask << 1;
        i++;
    }    
    turnLedOn(NUM_STATES-i+2);

}


//*****************************************************************************
//
//!  \brief  Unsets a state from the state machine
//!  Also handles LEDs
//!  
//!  \param  None
//!
//!  \return none
//!  
//
//*****************************************************************************
void unsetCC3000MachineState(char stat)
{
    char bitmask = stat;
    cc3000state &= ~bitmask;
    
    int i = FIRST_STATE_LED_NUM;
    int k = NUM_STATES; // Set to last element in state list
    
    // Set all upper bits to 0 as well since state machine cannot have
    // those states.
    while(bitmask < 0x80)
    {
        cc3000state &= ~bitmask;
        bitmask = bitmask << 1;
        i++;
    }
    
    // Turn off all upper state LEDs
    for(; i > FIRST_STATE_LED_NUM; i--)
    {
        turnLedOff(k);
        k--;
    }    
}

//*****************************************************************************
//
//!  \brief  Resets the State Machine
//!  
//!  \param  None
//!
//!  \return none
//!  
//
//*****************************************************************************
void resetCC3000StateMachine()
{
    cc3000state = CC3000_UNINIT;

    // Turn off all Board LEDs

    turnLedOff(CC3000_ON_IND);
    turnLedOff(CC3000_ASSOCIATED_IND);
    turnLedOff(CC3000_IP_ALLOC_IND);
    turnLedOff(CC3000_SERVER_INIT_IND);
    turnLedOff(CC3000_CLIENT_CONNECTED_IND);
    turnLedOff(CC3000_SENDING_DATA_IND);
    turnLedOff(CC3000_UNUSED1_IND);
    turnLedOff(CC3000_FTC_IND);
}

//*****************************************************************************
//
//!  \brief  Obtains the CC3000 Connection Information from the CC3000
//!  
//!  \param  None
//!
//!  \return none
//!  
//
//*****************************************************************************
#ifndef CC3000_TINY_DRIVER
tNetappIpconfigRetArgs * getCC3000Info()
{
    netapp_ipconfig(&ipinfo);
    return (&ipinfo);
}
#endif

//*****************************************************************************
//
//! StartSmartConfig
//!
//!  \param  None
//!
//!  \return none
//!
//!  \brief  The function triggers a smart configuration process on CC3000.
//!            it exists upon completion of the process
//
//*****************************************************************************

void StartSmartConfig(void)
{

    // Reset all the previous configuration
    //
    wlan_ioctl_set_connection_policy(0, 0, 0);    
        wlan_ioctl_del_profile(255);
    
    //Wait until CC3000 is dissconected
    while (ulCC3000Connected == 1)
    {
      //__delay_cycles(100);
      wait_us(5);
    }

    // Start blinking LED6 during Smart Configuration process
    turnLedOn(6);
    wlan_smart_config_set_prefix(aucCC3000_prefix);
    //wlan_first_time_config_set_prefix(aucCC3000_prefix);
    turnLedOff(6);
    
    // Start the SmartConfig start process
    wlan_smart_config_start(1);
    turnLedOn(6);
    
    //
    // Wait for Smart config finished
    // 
    while (ulSmartConfigFinished == 0)
    {
        //__delay_cycles(6000000);
        wait_ms(250);                                                                     
        turnLedOn(6);

        //__delay_cycles(6000000);
        wait_ms(250);        
        turnLedOff(6);
    }

    turnLedOff(6);

    // create new entry for AES encryption key
    nvmem_create_entry(NVMEM_AES128_KEY_FILEID,16);
    
    // write AES key to NVMEM
    aes_write_key((unsigned char *)(&smartconfigkey[0]));
    
    // Decrypt configuration information and add profile
    wlan_smart_config_process();
        
    //
    // Configure to connect automatically to the AP retrieved in the 
    // Smart config process
    //
    wlan_ioctl_set_connection_policy(0, 0, 1);
    
    //
    // reset the CC3000
    // 
    wlan_stop();
    //__delay_cycles(600000);
    wait_ms(25);
    wlan_start(0);

    unsigned char ConnectUsingSmartConfig  = 1; 
        ulSmartConfigFinished = 0;
    //
    // Mask out all non-required events
    //
    wlan_set_event_mask(HCI_EVNT_WLAN_KEEPALIVE|HCI_EVNT_WLAN_UNSOL_INIT|HCI_EVNT_WLAN_ASYNC_PING_REPORT);
}