Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: cc3000_hello_world_demo cc3000_simple_socket_demo cc3000_ntp_demo cc3000_ping_demo ... more
Diff: cc3000_spi.cpp
- Revision:
- 23:fed7f64dd520
- Parent:
- 0:615c697c33b0
- Child:
- 33:9e23b24fb4f3
diff -r fb34ac8d9af5 -r fed7f64dd520 cc3000_spi.cpp
--- a/cc3000_spi.cpp Thu Oct 03 20:22:45 2013 +0000
+++ b/cc3000_spi.cpp Thu Oct 03 21:00:00 2013 +0000
@@ -1,302 +1,302 @@
-/*****************************************************************************
-*
-* C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to
-* Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and
-* provided help.
-*
-* This version of "host driver" uses CC3000 Host Driver Implementation. Thus
-* read the following copyright:
-*
-* 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 "cc3000.h"
-#include "cc3000_spi.h"
-
-namespace mbed_cc3000 {
-
-cc3000_spi::cc3000_spi(PinName cc3000_irq, PinName cc3000_en, PinName cc3000_cs, SPI cc3000_spi, IRQn_Type irq_port, cc3000_event &event, cc3000_simple_link &simple_link)
- : _wlan_irq(cc3000_irq), _wlan_en(cc3000_en), _wlan_cs(cc3000_cs), _wlan_spi(cc3000_spi), _irq_port(irq_port),
- _event(event), _simple_link(simple_link) {
- /* TODO = clear pending interrupts for PORTS. This is dependent on the used chip */
-
- _wlan_spi.format(8,1);
- _wlan_spi.frequency(12000000);
- _function_pointer = _wlan_irq.fall(this, &cc3000_spi::WLAN_IRQHandler);
-
- _wlan_en = 0;
- _wlan_cs = 1;
-}
-
-cc3000_spi::~cc3000_spi() {
-
-}
-
-void cc3000_spi::wlan_irq_enable()
-{
- NVIC_EnableIRQ(_irq_port);
-}
-
-void cc3000_spi::wlan_irq_disable() {
- NVIC_DisableIRQ(_irq_port);
-}
-
-void cc3000_spi::wlan_irq_set(uint8_t value) {
- if (value)
- {
- _wlan_en = 1;
- }
- else
- {
- _wlan_en = 0;
- }
-}
-
-uint32_t cc3000_spi::wlan_irq_read() {
- return _wlan_irq.read();
-}
-
-void cc3000_spi::close() {
- if (_simple_link.get_received_buffer() != 0)
- {
- _simple_link.set_received_buffer(0);
- }
- wlan_irq_disable();
-}
-
-// void cc3000_spi::SpiReceiveHandler() {
-// _simple_link.usEventOrDataReceived = 1;
-// //_simple_link.pucReceivedData = (unsigned char *)pvBuffer;
-
-// hci_unsolicited_event_handler();
-// }
-
-
-/* TODO
- pRxPacket, pTxPacket do we need to hold this pointer ?
- SPIRxHandler - remove?
-*/
-void cc3000_spi::open() {
- _spi_info.spi_state = eSPI_STATE_POWERUP;
- //_spi_info.SPIRxHandler = pfRxHandler;
- _spi_info.tx_packet_length = 0;
- _spi_info.rx_packet_length = 0;
- //_rx_buffer[CC3000_RX_BUFFER_SIZE - 1] = CC3000_BUFFER_MAGIC_NUMBER;
- //_tx_buffer[CC3000_TX_BUFFER_SIZE - 1] = CC3000_BUFFER_MAGIC_NUMBER;
- wlan_irq_enable();
-}
-
-uint32_t cc3000_spi::first_write(uint8_t *buffer, uint16_t length) {
- _wlan_cs = 0;
- wait_us(50);
-
- /* first 4 bytes of the data */
- write_synchronous(buffer, 4);
- wait_us(50);
- write_synchronous(buffer + 4, length - 4);
- _spi_info.spi_state = eSPI_STATE_IDLE;
- _wlan_cs = 1;
-
- return 0;
-}
-
-
-uint32_t cc3000_spi::write(uint8_t *buffer, uint16_t length) {
- uint8_t pad = 0;
- // check the total length of the packet in order to figure out if padding is necessary
- if(!(length & 0x0001))
- {
- pad++;
- }
- buffer[0] = WRITE;
- buffer[1] = HI(length + pad);
- buffer[2] = LO(length + pad);
- buffer[3] = 0;
- buffer[4] = 0;
-
- length += (SPI_HEADER_SIZE + pad);
-
- // The magic number resides at the end of the TX/RX buffer (1 byte after the allocated size)
- // If the magic number is overwitten - buffer overrun occurred - we will be stuck here forever!
- uint8_t * transmit_buffer = _simple_link.get_transmit_buffer();
- if (transmit_buffer[CC3000_TX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER)
- {
- while (1);
- }
-
- if (_spi_info.spi_state == eSPI_STATE_POWERUP)
- {
- while (_spi_info.spi_state != eSPI_STATE_INITIALIZED);
- }
-
- if (_spi_info.spi_state == eSPI_STATE_INITIALIZED)
- {
- // TX/RX transaction over SPI after powerup: IRQ is low - send read buffer size command
- first_write(buffer, length);
- }
- else
- {
- // Prevent occurence of a race condition when 2 back to back packets are sent to the
- // device, so the state will move to IDLE and once again to not IDLE due to IRQ
- wlan_irq_disable();
-
- while (_spi_info.spi_state != eSPI_STATE_IDLE);
-
- _spi_info.spi_state = eSPI_STATE_WRITE_IRQ;
- //_spi_info.pTxPacket = buffer;
- _spi_info.tx_packet_length = length;
-
- // Assert the CS line and wait until the IRQ line is active, then initialize the write operation
- _wlan_cs = 0;
-
- wlan_irq_enable();
- }
-
- // Wait until the transaction ends
- while (_spi_info.spi_state != eSPI_STATE_IDLE);
-
- return 0;
-}
-
-void cc3000_spi::write_synchronous(uint8_t *data, uint16_t size) {
- while(size)
- {
- _wlan_spi.write(*data++);
- size--;
- }
-}
-
-void cc3000_spi::read_synchronous(uint8_t *data, uint16_t size) {
- for (uint32_t i = 0; i < size; i++)
- {
- data[i] = _wlan_spi.write(0x03);;
- }
-}
-
-uint32_t cc3000_spi::read_data_cont() {
- long data_to_recv;
- unsigned char *evnt_buff, type;
-
- //determine the packet type
- evnt_buff = _simple_link.get_received_buffer();
- data_to_recv = 0;
- STREAM_TO_UINT8((uint8_t *)(evnt_buff + SPI_HEADER_SIZE), HCI_PACKET_TYPE_OFFSET, type);
-
- switch(type)
- {
- case HCI_TYPE_DATA:
- {
- // Read the remaining data..
- STREAM_TO_UINT16((uint8_t *)(evnt_buff + SPI_HEADER_SIZE), HCI_DATA_LENGTH_OFFSET, data_to_recv);
- if (!((HEADERS_SIZE_EVNT + data_to_recv) & 1))
- {
- data_to_recv++;
- }
-
- if (data_to_recv)
- {
- read_synchronous(evnt_buff + 10, data_to_recv);
- }
- break;
- }
- case HCI_TYPE_EVNT:
- {
- // Calculate the rest length of the data
- STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE), HCI_EVENT_LENGTH_OFFSET, data_to_recv);
- data_to_recv -= 1;
- // Add padding byte if needed
- if ((HEADERS_SIZE_EVNT + data_to_recv) & 1)
- {
- data_to_recv++;
- }
-
- if (data_to_recv)
- {
- read_synchronous(evnt_buff + 10, data_to_recv);
- }
-
- _spi_info.spi_state = eSPI_STATE_READ_EOT;
- break;
- }
- }
- return (0);
-}
-
-void cc3000_spi::write_wlan_en(uint8_t value) {
- if (value) {
- _wlan_en = 1;
- } else {
- _wlan_en = 0;
- }
-}
-
-void cc3000_spi::WLAN_IRQHandler() {
- if (_spi_info.spi_state == eSPI_STATE_POWERUP)
- {
- // Inform HCI Layer that IRQ occured after powerup
- _spi_info.spi_state = eSPI_STATE_INITIALIZED;
- }
- else if (_spi_info.spi_state == eSPI_STATE_IDLE)
- {
- _spi_info.spi_state = eSPI_STATE_READ_IRQ;
- /* IRQ line goes low - acknowledge it */
- _wlan_cs = 0;
- read_synchronous(_simple_link.get_received_buffer(), 10);
- _spi_info.spi_state = eSPI_STATE_READ_EOT;
-
-
- // The header was read - continue with the payload read
- if (!read_data_cont())
- {
- // All the data was read - finalize handling by switching to the task
- // Trigger Rx processing
- wlan_irq_disable();
- _wlan_cs = 1;
- // The magic number resides at the end of the TX/RX buffer (1 byte after the allocated size)
- // If the magic number is overwitten - buffer overrun occurred - we will be stuck here forever!
- uint8_t *received_buffer = _simple_link.get_received_buffer();
- if (received_buffer[CC3000_RX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER)
- {
- while (1);
- }
- _spi_info.spi_state = eSPI_STATE_IDLE;
- _event.received_handler(received_buffer + SPI_HEADER_SIZE);
- }
- }
- else if (_spi_info.spi_state == eSPI_STATE_WRITE_IRQ)
- {
- write_synchronous(_simple_link.get_transmit_buffer(), _spi_info.tx_packet_length);
- _spi_info.spi_state = eSPI_STATE_IDLE;
- _wlan_cs = 1;
- }
-}
-
-}
+/*****************************************************************************
+*
+* C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to
+* Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and
+* provided help.
+*
+* This version of "host driver" uses CC3000 Host Driver Implementation. Thus
+* read the following copyright:
+*
+* 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 "cc3000.h"
+#include "cc3000_spi.h"
+
+namespace mbed_cc3000 {
+
+cc3000_spi::cc3000_spi(PinName cc3000_irq, PinName cc3000_en, PinName cc3000_cs, SPI cc3000_spi, IRQn_Type irq_port, cc3000_event &event, cc3000_simple_link &simple_link)
+ : _wlan_irq(cc3000_irq), _wlan_en(cc3000_en), _wlan_cs(cc3000_cs), _wlan_spi(cc3000_spi), _irq_port(irq_port),
+ _event(event), _simple_link(simple_link) {
+ /* TODO = clear pending interrupts for PORTS. This is dependent on the used chip */
+
+ _wlan_spi.format(8,1);
+ _wlan_spi.frequency(12000000);
+ _function_pointer = _wlan_irq.fall(this, &cc3000_spi::WLAN_IRQHandler);
+
+ _wlan_en = 0;
+ _wlan_cs = 1;
+}
+
+cc3000_spi::~cc3000_spi() {
+
+}
+
+void cc3000_spi::wlan_irq_enable()
+{
+ NVIC_EnableIRQ(_irq_port);
+}
+
+void cc3000_spi::wlan_irq_disable() {
+ NVIC_DisableIRQ(_irq_port);
+}
+
+void cc3000_spi::wlan_irq_set(uint8_t value) {
+ if (value)
+ {
+ _wlan_en = 1;
+ }
+ else
+ {
+ _wlan_en = 0;
+ }
+}
+
+uint32_t cc3000_spi::wlan_irq_read() {
+ return _wlan_irq.read();
+}
+
+void cc3000_spi::close() {
+ if (_simple_link.get_received_buffer() != 0)
+ {
+ _simple_link.set_received_buffer(0);
+ }
+ wlan_irq_disable();
+}
+
+// void cc3000_spi::SpiReceiveHandler() {
+// _simple_link.usEventOrDataReceived = 1;
+// //_simple_link.pucReceivedData = (unsigned char *)pvBuffer;
+
+// hci_unsolicited_event_handler();
+// }
+
+
+/* TODO
+ pRxPacket, pTxPacket do we need to hold this pointer ?
+ SPIRxHandler - remove?
+*/
+void cc3000_spi::open() {
+ _spi_info.spi_state = eSPI_STATE_POWERUP;
+ //_spi_info.SPIRxHandler = pfRxHandler;
+ _spi_info.tx_packet_length = 0;
+ _spi_info.rx_packet_length = 0;
+ //_rx_buffer[CC3000_RX_BUFFER_SIZE - 1] = CC3000_BUFFER_MAGIC_NUMBER;
+ //_tx_buffer[CC3000_TX_BUFFER_SIZE - 1] = CC3000_BUFFER_MAGIC_NUMBER;
+ wlan_irq_enable();
+}
+
+uint32_t cc3000_spi::first_write(uint8_t *buffer, uint16_t length) {
+ _wlan_cs = 0;
+ wait_us(50);
+
+ /* first 4 bytes of the data */
+ write_synchronous(buffer, 4);
+ wait_us(50);
+ write_synchronous(buffer + 4, length - 4);
+ _spi_info.spi_state = eSPI_STATE_IDLE;
+ _wlan_cs = 1;
+
+ return 0;
+}
+
+
+uint32_t cc3000_spi::write(uint8_t *buffer, uint16_t length) {
+ uint8_t pad = 0;
+ // check the total length of the packet in order to figure out if padding is necessary
+ if(!(length & 0x0001))
+ {
+ pad++;
+ }
+ buffer[0] = WRITE;
+ buffer[1] = HI(length + pad);
+ buffer[2] = LO(length + pad);
+ buffer[3] = 0;
+ buffer[4] = 0;
+
+ length += (SPI_HEADER_SIZE + pad);
+
+ // The magic number resides at the end of the TX/RX buffer (1 byte after the allocated size)
+ // If the magic number is overwitten - buffer overrun occurred - we will be stuck here forever!
+ uint8_t * transmit_buffer = _simple_link.get_transmit_buffer();
+ if (transmit_buffer[CC3000_TX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER)
+ {
+ while (1);
+ }
+
+ if (_spi_info.spi_state == eSPI_STATE_POWERUP)
+ {
+ while (_spi_info.spi_state != eSPI_STATE_INITIALIZED);
+ }
+
+ if (_spi_info.spi_state == eSPI_STATE_INITIALIZED)
+ {
+ // TX/RX transaction over SPI after powerup: IRQ is low - send read buffer size command
+ first_write(buffer, length);
+ }
+ else
+ {
+ // Prevent occurence of a race condition when 2 back to back packets are sent to the
+ // device, so the state will move to IDLE and once again to not IDLE due to IRQ
+ wlan_irq_disable();
+
+ while (_spi_info.spi_state != eSPI_STATE_IDLE);
+
+ _spi_info.spi_state = eSPI_STATE_WRITE_IRQ;
+ //_spi_info.pTxPacket = buffer;
+ _spi_info.tx_packet_length = length;
+
+ // Assert the CS line and wait until the IRQ line is active, then initialize the write operation
+ _wlan_cs = 0;
+
+ wlan_irq_enable();
+ }
+
+ // Wait until the transaction ends
+ while (_spi_info.spi_state != eSPI_STATE_IDLE);
+
+ return 0;
+}
+
+void cc3000_spi::write_synchronous(uint8_t *data, uint16_t size) {
+ while(size)
+ {
+ _wlan_spi.write(*data++);
+ size--;
+ }
+}
+
+void cc3000_spi::read_synchronous(uint8_t *data, uint16_t size) {
+ for (uint32_t i = 0; i < size; i++)
+ {
+ data[i] = _wlan_spi.write(0x03);;
+ }
+}
+
+uint32_t cc3000_spi::read_data_cont() {
+ long data_to_recv;
+ unsigned char *evnt_buff, type;
+
+ //determine the packet type
+ evnt_buff = _simple_link.get_received_buffer();
+ data_to_recv = 0;
+ STREAM_TO_UINT8((uint8_t *)(evnt_buff + SPI_HEADER_SIZE), HCI_PACKET_TYPE_OFFSET, type);
+
+ switch(type)
+ {
+ case HCI_TYPE_DATA:
+ {
+ // Read the remaining data..
+ STREAM_TO_UINT16((uint8_t *)(evnt_buff + SPI_HEADER_SIZE), HCI_DATA_LENGTH_OFFSET, data_to_recv);
+ if (!((HEADERS_SIZE_EVNT + data_to_recv) & 1))
+ {
+ data_to_recv++;
+ }
+
+ if (data_to_recv)
+ {
+ read_synchronous(evnt_buff + 10, data_to_recv);
+ }
+ break;
+ }
+ case HCI_TYPE_EVNT:
+ {
+ // Calculate the rest length of the data
+ STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE), HCI_EVENT_LENGTH_OFFSET, data_to_recv);
+ data_to_recv -= 1;
+ // Add padding byte if needed
+ if ((HEADERS_SIZE_EVNT + data_to_recv) & 1)
+ {
+ data_to_recv++;
+ }
+
+ if (data_to_recv)
+ {
+ read_synchronous(evnt_buff + 10, data_to_recv);
+ }
+
+ _spi_info.spi_state = eSPI_STATE_READ_EOT;
+ break;
+ }
+ }
+ return (0);
+}
+
+void cc3000_spi::write_wlan_en(uint8_t value) {
+ if (value) {
+ _wlan_en = 1;
+ } else {
+ _wlan_en = 0;
+ }
+}
+
+void cc3000_spi::WLAN_IRQHandler() {
+ if (_spi_info.spi_state == eSPI_STATE_POWERUP)
+ {
+ // Inform HCI Layer that IRQ occured after powerup
+ _spi_info.spi_state = eSPI_STATE_INITIALIZED;
+ }
+ else if (_spi_info.spi_state == eSPI_STATE_IDLE)
+ {
+ _spi_info.spi_state = eSPI_STATE_READ_IRQ;
+ /* IRQ line goes low - acknowledge it */
+ _wlan_cs = 0;
+ read_synchronous(_simple_link.get_received_buffer(), 10);
+ _spi_info.spi_state = eSPI_STATE_READ_EOT;
+
+
+ // The header was read - continue with the payload read
+ if (!read_data_cont())
+ {
+ // All the data was read - finalize handling by switching to the task
+ // Trigger Rx processing
+ wlan_irq_disable();
+ _wlan_cs = 1;
+ // The magic number resides at the end of the TX/RX buffer (1 byte after the allocated size)
+ // If the magic number is overwitten - buffer overrun occurred - we will be stuck here forever!
+ uint8_t *received_buffer = _simple_link.get_received_buffer();
+ if (received_buffer[CC3000_RX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER)
+ {
+ while (1);
+ }
+ _spi_info.spi_state = eSPI_STATE_IDLE;
+ _event.received_handler(received_buffer + SPI_HEADER_SIZE);
+ }
+ }
+ else if (_spi_info.spi_state == eSPI_STATE_WRITE_IRQ)
+ {
+ write_synchronous(_simple_link.get_transmit_buffer(), _spi_info.tx_packet_length);
+ _spi_info.spi_state = eSPI_STATE_IDLE;
+ _wlan_cs = 1;
+ }
+}
+
+}
SimpleLink Wi-Fi CC3000
Avnet Wi-Go System