Steve Sims / X_NUCLEO_IDW01M1_AP

Dependents:   X_NUCLEO_IDW01M1_AP_Test

Fork of X_NUCLEO_IDW01M1 by ST

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SpwfSADevice.cpp Source File

SpwfSADevice.cpp

Go to the documentation of this file.
00001 /* mbed Microcontroller Library
00002 * Copyright (c) 20015 ARM Limited
00003 *
00004 * Licensed under the Apache License, Version 2.0 (the "License");
00005 * you may not use this file except in compliance with the License.
00006 * You may obtain a copy of the License at
00007 *
00008 *     http://www.apache.org/licenses/LICENSE-2.0
00009 *
00010 * Unless required by applicable law or agreed to in writing, software
00011 * distributed under the License is distributed on an "AS IS" BASIS,
00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013 * See the License for the specific language governing permissions and
00014 * limitations under the License.
00015 */
00016  
00017 /**
00018   ******************************************************************************
00019   * @file    SpwfSADevice.cpp 
00020   * @author  STMicroelectronics
00021   * @brief   Implementation of SpwfSADevice class for Wi-Fi mbed
00022   ******************************************************************************
00023   * @copy
00024   *
00025   * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
00026   * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
00027   * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
00028   * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
00029   * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
00030   * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
00031   *
00032   * <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
00033   ******************************************************************************
00034   */ 
00035   
00036 
00037 #include "SpwfSADevice.h" 
00038 #include "wifi_module.h"
00039 
00040 
00041 #ifdef __cplusplus
00042 extern "C" {
00043 #endif
00044   
00045 void Rx_irq_handler(void);
00046 void Wifi_scheduler(void);
00047 void Wifi_ticker(void);
00048 
00049 #ifdef __cplusplus
00050 }
00051 #endif
00052 
00053 extern void setSpwfSADevice(SpwfSADevice * dev);
00054 
00055 #define FORMAT_HEX_STRING       "0x%08x"
00056 #define HEX_STRING_LENGTH       11
00057 
00058 /**
00059 * @brief  SpwfSADevice constructor         
00060 * @param  tx: Pin USART TX  
00061 *         rx: Pin USART RX
00062 *         rst: reset pin for Spwf module
00063 *         wkup: reset pin for Spwf module
00064 *         rts: Pin USART RTS
00065 * @retval none
00066 */
00067 SpwfSADevice::SpwfSADevice(PinName tx, PinName rx, PinName rst, PinName wkup, PinName rts):
00068     uart_(tx,rx), 
00069     term_(SERIAL_TX, SERIAL_RX),
00070     wakeup_(wkup, PIN_INPUT, PullNone, 0),
00071     rst_(rst, PIN_INPUT, PullNone, 1),     
00072     rts_(rts, PIN_INPUT, PullUp, 0)
00073 {
00074     setSpwfSADevice(this);
00075     sync_wait_signal = false;
00076     wait_for_incoming_client = false;
00077     wait_for_socket_data = false;
00078 }
00079 
00080 /**
00081 * @brief  SpwfSADevice destructor         
00082 * @param  none
00083 * @retval none
00084 */
00085 SpwfSADevice::~SpwfSADevice(void)
00086 {
00087     //de-constructor
00088 }
00089 
00090 /**
00091 * @brief  init function
00092           initializes timers, gpios, uart
00093 * @param  none
00094 * @retval error value
00095 */
00096 int SpwfSADevice::init(void) 
00097 {
00098     WiFi_Status_t status = WiFi_MODULE_SUCCESS;
00099     Timer timer;
00100     
00101     timer.start();    
00102     rst_.output();
00103     wakeup_.output();
00104     rts_.output();
00105     
00106     term_.baud(9600);
00107     term_.format(8, SerialBase::None, 1);
00108   
00109     uart_.baud(115200);
00110     uart_.format(8, SerialBase::None, 1);
00111     uart_.set_flow_control(SerialBase::RTS, PA_12, NC);//RTSCTS
00112     uart_.attach(Rx_irq_handler, SerialBase::RxIrq);
00113 
00114     config.power=wifi_active;
00115     config.power_level=max;
00116     config.dhcp=on;//use DHCP IP address
00117     config.ip_addr = "192.168.0.50";
00118     config.netmask_addr = "255.255.255.0";
00119     config.gateway_addr = "192.168.0.1";
00120     config.dns_addr = "192.168.0.1";
00121     
00122     /*Initialize the tickers*/
00123     wifi_isr.attach_us(Wifi_ticker, 1000); //decreasing the time period to 1ms may be causing overrun issue with UART?\
00124                                                 //UART error not evident but characters are sometimes missing in pipeline(ring_buffer)\
00125                                                 //specifically in the +WIND:25:WiFi Association with 'STM' successful WIND (why specifically this?)
00126     
00127     wifi_callback.attach_us(Wifi_scheduler, 5000);//How low can we go?
00128         
00129     sync_wait_signal = false;
00130     status = wifi_init(&config);
00131     if(status!=WiFi_MODULE_SUCCESS)
00132     {
00133         return -1;
00134     }
00135     while(!sync_wait_signal)
00136     {
00137         if (timer.read_ms() > _timeout) {
00138             return -1;
00139         }
00140         __NOP();
00141     }
00142     
00143     return 0;
00144 }
00145 
00146 /**
00147 * @brief  network connect
00148           wrapper function for FW
00149 * @param  ssid: Access Point (AP) Name String  
00150 *         sec_key: Password String for AP
00151 *         priv_mode: type of security supported (FW mode)
00152 * @retval NSAPI Error Type
00153 */
00154 int SpwfSADevice::connect(char * ssid, char * sec_key, WiFi_Priv_Mode priv_mode) 
00155 {
00156     WiFi_Status_t status = WiFi_MODULE_SUCCESS;
00157     Timer timer;
00158     
00159     timer.start();
00160     sync_wait_signal = false;
00161     status = wifi_connect(ssid, sec_key, priv_mode);
00162     if(status!=WiFi_MODULE_SUCCESS)
00163     {
00164         return -1;
00165     }       
00166     
00167     while(!sync_wait_signal)
00168     {
00169         if (timer.read_ms() > _timeout) {
00170             return -1;
00171         }
00172         __NOP();
00173     } 
00174     
00175     return 0;
00176 }
00177 
00178 /**
00179 * @brief start the mini access point
00180 * @param ssid: start with this SSID
00181 * @param sec_key: passphrase for STAtions to connect with
00182 * @param priv_mode: type of security to set up with
00183 * @param channel_num: WiFi channel to use
00184 * @param data_rates: bitmap of operational data rates to support
00185 * @retval NSAPI Error Type
00186 */
00187 int SpwfSADevice::start_access_point(char * ssid, char * sec_key, WiFi_Priv_Mode priv_mode, int channel_num, unsigned int data_rates)
00188 {
00189     WiFi_Status_t status = WiFi_MODULE_SUCCESS;
00190     Timer timer;
00191     
00192     timer.start();
00193     
00194     // Reset the data rate values
00195     uint32_t modeNEnabled = 1;
00196     char oprMask[] = "0x003fffcf";
00197     if (0x3fffcf != data_rates)
00198     {
00199         // All data rates must be enabled to allow wireless N (high throughput/HT) mode
00200         modeNEnabled = 0;
00201         sprintf(oprMask, (const char*)FORMAT_HEX_STRING, data_rates);
00202 
00203         // Different basic rate mask
00204         char basMask[HEX_STRING_LENGTH];
00205         sprintf(basMask, FORMAT_HEX_STRING, data_rates & 0xf);
00206         status = SET_Configuration_Addr(WIFI_BAS_RATE_MASK, basMask);
00207         if(status != WiFi_MODULE_SUCCESS) return -1;
00208     }
00209     
00210     status = SET_Configuration_Value(WIFI_HT_MODE, modeNEnabled);
00211     if(status != WiFi_MODULE_SUCCESS && modeNEnabled) {
00212         return -1;
00213     }
00214     status = SET_Configuration_Addr(WIFI_OPR_RATE_MASK, oprMask);
00215     if(status != WiFi_MODULE_SUCCESS) return -1;
00216 
00217     // Start the access point
00218     sync_wait_signal = false;        
00219     status = wifi_ap_start((uint8_t*)ssid, (uint8_t)channel_num);
00220     if(status!=WiFi_MODULE_SUCCESS)
00221     {
00222         return -1;
00223     }        
00224     
00225     while(!sync_wait_signal)
00226     {
00227         if (timer.read_ms() > _timeout) {
00228             return -1;
00229         }
00230         __NOP();
00231     } 
00232     
00233     return 0;
00234 }
00235 
00236 /**
00237 * @brief  network disconnect
00238           wrapper function for FW
00239 * @param  none
00240 * @retval error value
00241 */
00242 int SpwfSADevice::disconnect()
00243 {
00244     WiFi_Status_t status = WiFi_MODULE_SUCCESS;
00245 
00246     status = wifi_disconnect();//will set to Idle Mode
00247     if(status!=WiFi_MODULE_SUCCESS)
00248     {
00249         return -1;
00250     }
00251     
00252     return 0;
00253 }
00254 
00255 /** 
00256 * @brief  Get the local IP address
00257 *         wrapper function for FW
00258 * @param  none
00259 * @retval Null-terminated representation of the local IP address
00260 *         or null if not yet connected
00261 */
00262 const char *SpwfSADevice::getIPAddress()
00263 {
00264     WiFi_Status_t status = WiFi_MODULE_SUCCESS;
00265 
00266     status = WiFi_Get_IP_Address((uint8_t *)_ip_buffer);
00267     
00268     if(status!=WiFi_MODULE_SUCCESS)
00269     {
00270         return NULL;
00271     } else 
00272         return _ip_buffer;
00273 }
00274 
00275 /** 
00276 * @brief  Get the MAC address
00277 *         wrapper function for FW
00278 * @param  none
00279 * @retval Null-terminated representation of the MAC address
00280 *         or null if not yet connected
00281 */
00282 const char *SpwfSADevice::getMACAddress()
00283 {
00284     WiFi_Status_t status = WiFi_MODULE_SUCCESS;
00285 
00286     status = WiFi_Get_MAC_Address((uint8_t *)_mac_buffer);
00287     
00288     if(status!=WiFi_MODULE_SUCCESS)
00289     {
00290         return NULL;
00291     } else 
00292         return _mac_buffer;
00293 }
00294 
00295 /**
00296 * @brief  connect to a remote socket
00297 * @param  hostname: address of socket
00298           port_number: port number to connect
00299           protocol: TCP/UDP protocol
00300 *         sock_id: pointer to socket ID returned by FW
00301 * @retval error value
00302 */
00303 int SpwfSADevice::socket_client_open(uint8_t * hostname, uint32_t port_number, uint8_t * protocol, uint8_t * sock_id)
00304 {
00305     WiFi_Status_t status = WiFi_MODULE_SUCCESS;
00306 
00307     //Timeout of synchronous functions?
00308     status = wifi_socket_client_open(hostname, port_number, protocol, sock_id);
00309     if(status!=WiFi_MODULE_SUCCESS)
00310     {
00311         *sock_id = 99;//make sure socket id is not set(set to out of bounds of SPWFSA_SOCKET_COUNT range)
00312         return -1;
00313     }
00314     
00315     return 0;
00316 }
00317 
00318 /**
00319 * @brief  write to a remote socket
00320 * @param  sock_id: FW ID of the socket
00321           DataLength: size of the data
00322           pData: pointer to data
00323 * @retval error value
00324 */
00325 int SpwfSADevice::socket_client_write(uint8_t sock_id, uint16_t DataLength,char * pData)
00326 {
00327     int status=0;//number of bytes
00328 
00329     status = wifi_socket_client_write(sock_id, DataLength, pData);
00330     //map error to enum ns_error_t 
00331     
00332     if(status > 0)
00333     {
00334         return status;
00335     }
00336     return 0;
00337 }
00338 
00339 /**
00340 * @brief  receive from a remote socket
00341 * @param  sock_id: FW ID of the socket
00342           DataLength: size of the data
00343           pData: pointer to data
00344 * @retval error value
00345 */
00346 int SpwfSADevice::socket_client_recv(uint8_t sock_id, uint16_t RecvLength,char * pData)
00347 {
00348     static Timer recv_timer;
00349     //char debug_str[10];    
00350     static bool recv_call = true;
00351     
00352     if(recv_call)
00353     {
00354         //debug_print("\r\nrecv_call\r\n");
00355         //__disable_irq();
00356         wait_for_socket_data = false;
00357         recv_buff = (uint8_t*)pData;
00358         //__enable_irq();
00359         if(_timeout>0)
00360         recv_timer.start();
00361         recv_call = false;
00362         bytes_to_read = RecvLength;        
00363         bytes_read=0;
00364     }
00365             
00366     
00367     if(wait_for_socket_data || recv_timer.read_ms() >= _timeout)
00368     {      
00369         recv_call = true;
00370         _timeout = 0;
00371         wait_for_socket_data = true;
00372         recv_timer.stop();
00373         recv_timer.reset();
00374         wait_ms(1);
00375         if(bytes_read == 0) //<bytes_to_read?? 
00376             return -1;//return error if no bytes are read!
00377         else 
00378             return bytes_read;//return amount of data arrived so far
00379     }
00380     wait_ms(1); //CHECK:TODO: Need to wait to allow other IRQ's to run in case of non-blocking call?
00381     return -1;    
00382 }
00383 
00384 /**
00385 * @brief  scan the network
00386 * @param  scan_result: scan result data pointer
00387           max_scan_number: size of the scan result 
00388 * @retval error value
00389 */
00390 void SpwfSADevice::network_scan(wifi_scan *scan_result, uint16_t max_scan_number)
00391 {
00392     WiFi_Status_t status = WiFi_MODULE_SUCCESS;
00393     
00394     status = wifi_network_scan(scan_result, max_scan_number);
00395     if(status!=WiFi_MODULE_SUCCESS)
00396     {
00397         return;
00398     }
00399 }
00400 
00401 /**
00402 * @brief  HTTP GET from remote host
00403 * @param  hostname: address of remote host
00404           path: path to resource
00405           port_number: port number
00406 * @retval none
00407 */
00408 void SpwfSADevice::http_get(uint8_t * hostname, uint8_t * path, uint32_t port_number)
00409 {
00410     WiFi_Status_t status = WiFi_MODULE_SUCCESS;
00411     
00412     status = wifi_http_get((uint8_t *)hostname, (uint8_t *)path, port_number);
00413     if(status!=WiFi_MODULE_SUCCESS)
00414     {
00415         return;
00416     }    
00417 }
00418 
00419 /**
00420 * @brief  HTTP GET from remote host
00421 * @param  url_path: complete url of remote resource
00422 * @retval none
00423 */
00424 void SpwfSADevice::http_post(uint8_t * url_path)
00425 {
00426     WiFi_Status_t status = WiFi_MODULE_SUCCESS;
00427     
00428     status = wifi_http_post(url_path);
00429     if(status!=WiFi_MODULE_SUCCESS)
00430     {
00431         return;
00432     }    
00433 }
00434 
00435 /**
00436 * @brief  FW callback with data in socket
00437 * @param  sock_id: FW ID of the socket
00438           data_ptr: pointer to data from FW
00439           message_size: total data to arrive
00440           chunk_size: size of the data in this callback (<= message_size)
00441 * @retval none
00442 */
00443 void SpwfSADevice::signal_data_receive(uint8_t socket_id, uint8_t * data_ptr, uint32_t message_size, uint32_t chunk_size)
00444 {
00445     char debug_str[50];
00446     //Data will be copied or returned to user only if there is a pending request
00447     //Copy data to pData
00448     //sprintf((char*)debug_str,"sock_id: %d, size: %d, chunk: %d\r\n",socket_id, message_size, chunk_size); 
00449     //debug_print(debug_str);
00450             
00451     if(recv_buff && !wait_for_socket_data)
00452     {
00453         if((bytes_read + chunk_size)<= bytes_to_read)
00454         {
00455             memcpy(recv_buff + bytes_read, data_ptr, chunk_size);//only copy bytes_to_read asked by user//rest of the data is lost!!
00456             bytes_read += chunk_size;
00457         }
00458         else
00459             {
00460                 uint32_t x_size = (bytes_read + chunk_size) - bytes_to_read;
00461                 memcpy(recv_buff + bytes_read, data_ptr, chunk_size-x_size);
00462                 bytes_read += (chunk_size-x_size);
00463             }          
00464         
00465         if(bytes_read >= bytes_to_read)
00466         {
00467             __disable_irq();
00468             wait_for_socket_data = true;
00469             __enable_irq();
00470         }
00471     }
00472     else
00473     {
00474         debug_print("\r\n Socket:: Data Dropped: ");
00475         sprintf((char*)debug_str,"%d\r\n",chunk_size); 
00476         debug_print(debug_str);
00477         __disable_irq();
00478         wait_for_socket_data = true;
00479         __enable_irq();
00480     }
00481 }
00482 
00483 /**
00484 * @brief  synchronization function called from FW (used for connect,disconnect, ready, etc.)
00485 * @param  code: Status code value returned
00486 * @retval none
00487 */
00488 void SpwfSADevice::signal_synch_wait(WiFi_Status_t code)
00489 {
00490     if(code == WiFi_DISASSOCIATION)
00491     {
00492         //do nothing
00493     } 
00494     else
00495     {
00496         __disable_irq();
00497         sync_wait_signal = true;
00498         __enable_irq();
00499     }
00500 }
00501 
00502 /**
00503 * @brief  close a client socket
00504 * @param  sock_close_id: FW ID of the socket to close
00505 * @retval error value
00506 */
00507 int SpwfSADevice::socket_client_close(uint8_t sock_close_id)
00508 {
00509     WiFi_Status_t status = WiFi_MODULE_SUCCESS;
00510 
00511     status = wifi_socket_client_close(sock_close_id);
00512     //map error to enum ns_error_t 
00513     if(status!=WiFi_MODULE_SUCCESS)
00514     {
00515         return -1;
00516     }    
00517     
00518     return 0;
00519 }
00520 
00521 /**
00522 * @brief  open a server socket
00523 * @param  port_number: port number to listen on
00524 *         protocol: TCP/UDP protocol
00525 * @retval error value
00526 */
00527 int SpwfSADevice::socket_server_open(uint32_t port_number, uint8_t * protocol)
00528 {
00529     WiFi_Status_t status = WiFi_MODULE_SUCCESS;
00530 
00531     status = wifi_socket_server_open(port_number, protocol);
00532     //map error to enum ns_error_t 
00533     if(status!=WiFi_MODULE_SUCCESS)
00534     {
00535         return -1;
00536     }    
00537     
00538     return 0;
00539 }
00540 
00541 /**
00542 * @brief  write to a server socket
00543 * @param  data_length: size of the data
00544 *         pdata: pointer to data
00545 * @retval error value
00546 */
00547 int SpwfSADevice::socket_server_write(uint16_t data_length,char * pdata)
00548 {    
00549     int status = 0;//number of bytes
00550 
00551     status = wifi_socket_server_write(data_length, pdata);
00552     //map error to enum ns_error_t 
00553     if(status > 0)
00554     {
00555         return status;
00556     }
00557     return 0;
00558 }
00559 
00560 /**
00561 * @brief  close a server socket
00562 * @param  none (only one server socket supported)
00563 * @retval error value
00564 */
00565 int SpwfSADevice::socket_server_close(void)
00566 {    
00567     WiFi_Status_t status = WiFi_MODULE_SUCCESS;
00568 
00569     status = wifi_socket_server_close();
00570     //map error to enum ns_error_t 
00571     if(status!=WiFi_MODULE_SUCCESS)
00572     {
00573         return -1;
00574     }    
00575     
00576     return 0;
00577 }
00578 
00579 /**
00580 * @brief  attach/remove IRQ handler to UART
00581 * @param  attach: attach/remove boolean
00582 * @retval none
00583 */
00584 void SpwfSADevice::spwf_attach_irq(wifi_bool attach) 
00585 {
00586     if(attach)
00587     {
00588         uart_.attach(Rx_irq_handler, SerialBase::RxIrq);
00589     }
00590     else
00591     {
00592         uart_.attach(NULL, SerialBase::RxIrq);
00593     }
00594 }
00595 
00596 /**
00597 * @brief  write byte(s) to the UART
00598 * @param  cmd: pointer to data
00599 *         size: size of data
00600 * @retval error value
00601 */
00602 int SpwfSADevice::spwf_send(const char * cmd, uint16_t size) 
00603 {
00604     Timer timer;
00605     int i, bytes;
00606     //timer.start();
00607     
00608     //uart_.puts(cmd);//string may contain '\0' character in between hence not used
00609     
00610     for(i=0;i<size;i++)
00611     {
00612         uart_.putc(cmd[i]);        
00613         //if (timer.read_ms() > _timeout) {
00614             //return -1;
00615         //}
00616     }
00617     
00618     bytes = (int) size - 2;//we send 2 bytes extra for module
00619     return bytes;
00620 }
00621 
00622 /**
00623 * @brief  read a byte from the UART
00624 * @param  none
00625 * @retval byte character
00626 */
00627 char SpwfSADevice::spwf_get(void) 
00628 {
00629     return(uart_.getc());
00630 }
00631 
00632 /**
00633 * @brief  (re)set the SPWF wakeup GPIO pin
00634 * @param  wake (re)set value
00635 * @retval none
00636 */
00637 void SpwfSADevice::spwf_wakeup(int wake)
00638 {
00639     wakeup_.write(wake);
00640 }
00641 
00642 /**
00643 * @brief  (re)set the SPWF reset GPIO pin
00644 * @param  reset (re)set value
00645 * @retval none
00646 */
00647 void SpwfSADevice::spwf_reset(int reset)
00648 {
00649     rst_.write(reset);
00650 }
00651 
00652 /**
00653 * @brief  (re)set the SPWF RTS GPIO line
00654 * @param  rts (re)set value
00655 * @retval none
00656 */
00657 void SpwfSADevice::spwf_rts(int rts)
00658 {
00659     rts_.write(rts);
00660 }
00661 
00662 /**
00663 * @brief  read the SPWF RTS GPIO pin
00664 * @param  none
00665 * @retval none
00666 */
00667 int SpwfSADevice::spwf_read_rts()
00668 {
00669     return(rts_.read());
00670 }
00671 
00672 /**
00673 * @brief  send debug print to serial terminal
00674 * @param  string: data for debug print
00675 * @retval none
00676 */
00677 void SpwfSADevice::debug_print(const char * string)
00678 {
00679     term_.puts(string);
00680 }
00681 
00682 /**
00683 * @brief  (re)set the switch for incoming client (server socket)
00684 * @param  set: boolean to (re)set
00685 * @retval none
00686 */
00687 void SpwfSADevice::set_wait_for_incoming_client(bool set)
00688 {
00689     wait_for_incoming_client = set;    
00690 }
00691 
00692 /**
00693 * @brief  get the switch for incoming client (server socket)
00694 * @param  none
00695 * @retval boolean
00696 */
00697 bool SpwfSADevice::get_wait_for_incoming_client()
00698 {
00699     return wait_for_incoming_client;
00700 }
00701