Toyomasa Watarai
/
Mbed-example-WS-W27
Mbed Cloud example program for workshop in W27 2018.
easy-connect/wifi-x-nucleo-idw01m1/SPWFSAxx.h
- Committer:
- MACRUM
- Date:
- 2018-06-30
- Revision:
- 0:119624335925
File content as of revision 0:119624335925:
/* SPWFSAxx Devices * Copyright (c) 2015 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SPWFSAXX_H #define SPWFSAXX_H #include "mbed.h" #include "ATCmdParser.h" #include "BlockExecuter.h" /* Common SPWFSAxx macros */ #define SPWFXX_WINDS_LOW_ON "0x00000000" #define SPWFXX_DEFAULT_BAUD_RATE 115200 #define SPWFXX_MAX_TRIALS 3 #if !defined(SPWFSAXX_RTS_PIN) #define SPWFSAXX_RTS_PIN NC #endif // !defined(SPWFSAXX_RTS_PIN) #if !defined(SPWFSAXX_CTS_PIN) #define SPWFSAXX_CTS_PIN NC #endif // !defined(SPWFSAXX_CTS_PIN) #define SPWFXX_ERR_OK (+1) #define SPWFXX_ERR_OOM (-1) #define SPWFXX_ERR_READ (-2) #define SPWFXX_ERR_LEN (-3) /* Max number of sockets & packets */ #define SPWFSA_SOCKET_COUNT (8) #define SPWFSA_MAX_PACKETS (4) #define PENDING_DATA_SLOTS (13) /* Pending data packets size buffer */ class SpwfRealPendingPackets { public: SpwfRealPendingPackets() { reset(); } void add(uint32_t new_cum_size) { MBED_ASSERT(new_cum_size >= cumulative_size); if(new_cum_size == cumulative_size) { /* nothing to do */ return; } /* => `new_cum_size > cumulative_size` */ real_pkt_sizes[last_pkt_ptr] = (uint16_t)(new_cum_size - cumulative_size); cumulative_size = new_cum_size; last_pkt_ptr = (last_pkt_ptr + 1) % PENDING_DATA_SLOTS; MBED_ASSERT(first_pkt_ptr != last_pkt_ptr); } uint32_t get(void) { if(empty()) return 0; return real_pkt_sizes[first_pkt_ptr]; } uint32_t cumulative(void) { return cumulative_size; } uint32_t remove(uint32_t size) { MBED_ASSERT(!empty()); uint32_t ret = real_pkt_sizes[first_pkt_ptr]; first_pkt_ptr = (first_pkt_ptr + 1) % PENDING_DATA_SLOTS; MBED_ASSERT(ret == size); MBED_ASSERT(ret <= cumulative_size); cumulative_size -= ret; return ret; } void reset(void) { memset(this, 0, sizeof(*this)); } private: bool empty(void) { if(first_pkt_ptr == last_pkt_ptr) { MBED_ASSERT(cumulative_size == 0); return true; } return false; } uint16_t real_pkt_sizes[PENDING_DATA_SLOTS]; uint8_t first_pkt_ptr; uint8_t last_pkt_ptr; uint32_t cumulative_size; }; class SpwfSAInterface; /** SPWFSAxx Interface class. This is an interface to a SPWFSAxx module. */ class SPWFSAxx { private: /* abstract class*/ SPWFSAxx(PinName tx, PinName rx, PinName rts, PinName cts, SpwfSAInterface &ifce, bool debug, PinName wakeup, PinName reset); public: /** * Init the SPWFSAxx * * @param mode mode in which to startup * @return true only if SPWFSAxx has started up correctly */ bool startup(int mode); /** * Connect SPWFSAxx to AP * * @param ap the name of the AP * @param passPhrase the password of AP * @param securityMode the security mode of AP (WPA/WPA2, WEP, Open) * @return true only if SPWFSAxx is connected successfully */ bool connect(const char *ap, const char *passPhrase, int securityMode); /** * Disconnect SPWFSAxx from AP * * @return true only if SPWFSAxx is disconnected successfully */ bool disconnect(void); /** * Get the IP address of SPWFSAxx * * @return null-terminated IP address or null if no IP address is assigned */ const char *getIPAddress(void); /** * Get the MAC address of SPWFSAxx * * @return null-terminated MAC address or null if no MAC address is assigned */ const char *getMACAddress(void); /** Get the local gateway * * @return Null-terminated representation of the local gateway * or null if no network mask has been received */ const char *getGateway(void); /** Get the local network mask * * @return Null-terminated representation of the local network mask * or null if no network mask has been received */ const char *getNetmask(void); /** Gets the current radio signal strength for active connection * * @return Connection strength in dBm (negative value) */ int8_t getRssi(); /** * Sends data to an open socket * * @param spwf_id module id of socket to send to * @param data data to be sent * @param amount amount of data to be sent - max 1024 * @param internal_id driver id of socket to send to * @return number of written bytes on success, negative on failure */ nsapi_size_or_error_t send(int spwf_id, const void *data, uint32_t amount, int internal_id); /** * Receives data from an open socket * * @param id id to receive from * @param data placeholder for returned information * @param amount number of bytes to be received * @param datagram receive a datagram packet * @return the number of bytes received */ int32_t recv(int id, void *data, uint32_t amount, bool datagram); /** * Closes a socket * * @param id id of socket to close, valid only 0-4 * @return true only if socket is closed successfully */ bool close(int id); /** * Allows timeout to be changed between commands * * @param timeout_ms timeout of the connection */ void setTimeout(uint32_t timeout_ms); /** * Attach a function to call whenever network state has changed * * @param func A pointer to a void function, or 0 to set as none */ void attach(Callback<void()> func); /** * Attach a function to call whenever network state has changed * * @param obj pointer to the object to call the member function on * @param method pointer to the member function to call */ template <typename T, typename M> void attach(T *obj, M method) { attach(Callback<void()>(obj, method)); } static const char _cr_ = '\x0d'; // '\r' carriage return static const char _lf_ = '\x0a'; // '\n' line feed private: UARTSerial _serial; ATCmdParser _parser; DigitalOut _wakeup; DigitalOut _reset; PinName _rts; PinName _cts; int _timeout; bool _dbg_on; int _pending_sockets_bitmap; SpwfRealPendingPackets _pending_pkt_sizes[SPWFSA_SOCKET_COUNT]; bool _network_lost_flag; SpwfSAInterface &_associated_interface; /** * Reset SPWFSAxx * * @return true only if SPWFSAxx resets successfully */ bool hw_reset(void); bool reset(void); /** * Check if SPWFSAxx is connected * * @return true only if the chip has an IP address */ bool isConnected(void); /** * Checks if data is available */ bool readable(void) { return _serial.FileHandle::readable(); } /** * Checks if data can be written */ bool writeable(void) { return _serial.FileHandle::writable(); } /** * Try to empty RX buffer * Can be used when commands fail receiving expected response to try to recover situation * @note Gives no guarantee that situation improves */ void empty_rx_buffer(void) { while(readable()) _parser.getc(); } /* block calling (external) callback */ volatile unsigned int _call_event_callback_blocked; Callback<void()> _callback_func; struct packet { struct packet *next; int id; uint32_t len; // data follows } *_packets, **_packets_end; void _packet_handler_th(void); void _execute_bottom_halves(void); void _network_lost_handler_th(void); void _network_lost_handler_bh(void); void _hard_fault_handler(void); void _wifi_hwfault_handler(void); void _server_gone_handler(void); #if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1 void _skip_oob(void); #endif bool _wait_wifi_hw_started(void); bool _wait_console_active(void); int _read_len(int); int _flush_in(char*, int); bool _winds_off(void); void _winds_on(void); void _read_in_pending(void); int _read_in_pkt(int spwf_id, bool close); int _read_in_packet(int spwf_id, uint32_t amount); void _recover_from_hard_faults(void); void _free_packets(int spwf_id); void _free_all_packets(void); void _process_winds(); virtual int _read_in(char*, int, uint32_t) = 0; bool _recv_delim_lf(void) { return (_parser.getc() == _lf_); } bool _recv_delim_cr(void) { return (_parser.getc() == _cr_); } bool _recv_delim_cr_lf(void) { return _recv_delim_cr() && _recv_delim_lf(); } bool _recv_ok(void) { return _parser.recv(SPWFXX_RECV_OK) && _recv_delim_lf(); } void _add_pending_packet_sz(int spwf_id, uint32_t size); void _add_pending_pkt_size(int spwf_id, uint32_t size) { _pending_pkt_sizes[spwf_id].add(size); } uint32_t _get_cumulative_size(int spwf_id) { return _pending_pkt_sizes[spwf_id].cumulative(); } uint32_t _remove_pending_pkt_size(int spwf_id, uint32_t size) { return _pending_pkt_sizes[spwf_id].remove(size); } uint32_t _get_pending_pkt_size(int spwf_id) { return _pending_pkt_sizes[spwf_id].get(); } void _reset_pending_pkt_sizes(int spwf_id) { _pending_pkt_sizes[spwf_id].reset(); } void _set_pending_data(int spwf_id) { _pending_sockets_bitmap |= (1 << spwf_id); } void _clear_pending_data(int spwf_id) { _pending_sockets_bitmap &= ~(1 << spwf_id); } bool _is_data_pending(int spwf_id) { return (_pending_sockets_bitmap & (1 << spwf_id)) ? true : false; } bool _is_data_pending(void) { if(_pending_sockets_bitmap != 0) return true; else return false; } void _packet_handler_bh(void) { /* read in other eventually pending packages */ _read_in_pending(); } /* Do not call the (external) callback in IRQ context while performing critical module operations */ void _event_handler(void); void _error_handler(void); void _call_callback(void) { if((bool)_callback_func) { _callback_func(); } } bool _is_event_callback_blocked(void) { return (_call_event_callback_blocked != 0); } void _block_event_callback(void) { _call_event_callback_blocked++; } void _unblock_event_callback(void) { MBED_ASSERT(_call_event_callback_blocked > 0); _call_event_callback_blocked--; if(_call_event_callback_blocked == 0) { _trigger_event_callback(); } } /* trigger call of (external) callback in case there is still data */ void _trigger_event_callback(void) { MBED_ASSERT(_call_event_callback_blocked == 0); /* if still data available */ if(readable()) { _call_callback(); } } char _ip_buffer[16]; char _gateway_buffer[16]; char _netmask_buffer[16]; char _mac_buffer[18]; char _msg_buffer[256]; private: friend class SPWFSA01; friend class SPWFSA04; friend class SpwfSAInterface; }; #endif // SPWFSAXX_H