1345 lines
45 KiB
C
1345 lines
45 KiB
C
|
|
// esp8266.c
|
||
|
|
// Driver for ESP8266 module to act as a WiFi client or server
|
||
|
|
// Currently restricted to one incoming or outgoing connection at a time
|
||
|
|
//
|
||
|
|
// Steven Prickett (steven.prickett@gmail.com)
|
||
|
|
// Modified version by Dung Nguyen, Wally Guzman
|
||
|
|
// Modified by Jonathan Valvano, March 28, 2017
|
||
|
|
// Consolidated by Andreas Gerstlauer, April 6, 2020
|
||
|
|
// Converted to MSPM0G3507 UART1 by Jonathan Valvano, Jan 19, 2026
|
||
|
|
// Added MSPM0G3507 UART2 by Jonathan Valvano, Jan 26, 2026
|
||
|
|
/*
|
||
|
|
THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
|
||
|
|
OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
|
||
|
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
|
||
|
|
VALVANO SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
|
||
|
|
OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
|
||
|
|
*/
|
||
|
|
|
||
|
|
// NOTE: see ESP8266 files in datasheets folder
|
||
|
|
|
||
|
|
/* Hardware connections
|
||
|
|
Vcc is a separate regulated 3.3V supply with at least 215mA
|
||
|
|
/------------------------------\
|
||
|
|
| chip 1 8 |
|
||
|
|
| Ant 2 7 |
|
||
|
|
| enna processor 3 6 |
|
||
|
|
| 4 5 |
|
||
|
|
\------------------------------/
|
||
|
|
Connects MSPM0
|
||
|
|
UART1 on (PA17/PA18) or UART2 on (PB17/PB18)
|
||
|
|
Reset on PA25
|
||
|
|
Ok to not access PB19 because of the internal pullup in ESP8266
|
||
|
|
ESP8266 MSPM0 Motor board version 7
|
||
|
|
1 URxD PA17 UART1 out of MSPM0, into ESP8266 115200 baud
|
||
|
|
2 GPIO0 +3.3V for normal operation (ground to flash)
|
||
|
|
3 GPIO2 PB19 GPIO, high/float on startup, has internal pullup, can be used for I/O
|
||
|
|
4 GND Gnd GND (70mA)
|
||
|
|
5 UTxD PA18 UART out of ESP8266, UART1 into MSPM0 115200 baud
|
||
|
|
6 Ch_PD chip select, 10k resistor to 3.3V
|
||
|
|
7 Reset PA25 MSPM0 GPIO output, can issue output low to cause hardware reset
|
||
|
|
8 Vcc regulated 3.3V supply with at least 70mA
|
||
|
|
|
||
|
|
ESP8266 MSPM0 Motor board version 7.1
|
||
|
|
1 URxD PB17 UART2 out of MSPM0, into ESP8266 115200 baud
|
||
|
|
2 GPIO0 +3.3V for normal operation (ground to flash)
|
||
|
|
3 GPIO2 PB19 GPIO, high/float on startup, has internal pullup, can be used for I/O
|
||
|
|
4 GND Gnd GND (70mA)
|
||
|
|
5 UTxD PB18 UART out of ESP8266, UART2 into MSPM0 115200 baud
|
||
|
|
6 Ch_PD chip select, 10k resistor to 3.3V
|
||
|
|
7 Reset PA25 MSPM0 GPIO output, can issue output low to cause hardware reset
|
||
|
|
8 Vcc regulated 3.3V supply with at least 70mA
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include <stdio.h>
|
||
|
|
#include <stdbool.h>
|
||
|
|
#include <stdint.h>
|
||
|
|
#include <string.h>
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <ti/devices/msp/msp.h>
|
||
|
|
#include "../inc/UART.h"
|
||
|
|
#include "../inc/Clock.h"
|
||
|
|
#include "../inc/FIFO.h"
|
||
|
|
#include "../RTOS_Labs_common/esp8266.h"
|
||
|
|
#include "../RTOS_Labs_common/WifiSettings.h" // access point parameters
|
||
|
|
#include "../RTOS_Labs_common/OS.h"
|
||
|
|
#include "../inc/LaunchPad.h"
|
||
|
|
|
||
|
|
/*
|
||
|
|
===========================================================
|
||
|
|
========== CONSTANTS ==========
|
||
|
|
===========================================================
|
||
|
|
*/
|
||
|
|
|
||
|
|
#define ESP8266_RST (1<<25) // PA25
|
||
|
|
|
||
|
|
//#define ESP8266_UART 1 // Motor board v7, UART1: U1Tx PA17, U1Rx PA18
|
||
|
|
#define ESP8266_UART 2 // Motor board v7.1, UART2: U2Tx PB17, U2Rx PB18
|
||
|
|
#if ESP8266_UART==1
|
||
|
|
#define ESP8266_RX PA18INDEX
|
||
|
|
#define ESP8266_TX PA17INDEX
|
||
|
|
#else
|
||
|
|
#define ESP8266_RX PB18INDEX
|
||
|
|
#define ESP8266_TX PB17INDEX
|
||
|
|
#endif
|
||
|
|
// defined in CriticalSection.s
|
||
|
|
long StartCritical(void);
|
||
|
|
void EndCritical(long);
|
||
|
|
|
||
|
|
void OS_InitSemaphore(Sema4_t *semaPt, int32_t value);
|
||
|
|
void OS_Signal(Sema4_t *semaPt);
|
||
|
|
void OS_Wait(Sema4_t *semaPt);
|
||
|
|
|
||
|
|
|
||
|
|
#define MAXTRY 1 // number of attempts to send command
|
||
|
|
|
||
|
|
// ESP responses
|
||
|
|
static const char ESP8266_READY_RESPONSE[] = "\r\nready\r\n";
|
||
|
|
static const char ESP8266_OK_RESPONSE[] = "\r\nOK\r\n";
|
||
|
|
static const char ESP8266_ERROR_RESPONSE[] = "\r\nERROR\r\n";
|
||
|
|
static const char ESP8266_FAIL_RESPONSE[] = "\r\nFAIL\r\n";
|
||
|
|
static const char ESP8266_SENDOK_RESPONSE[] = "\r\nSEND OK\r\n";
|
||
|
|
|
||
|
|
/*
|
||
|
|
=============================================================
|
||
|
|
========== GLOBAL VARIABLES ==========
|
||
|
|
=============================================================
|
||
|
|
*/
|
||
|
|
|
||
|
|
// Globals for UART driver
|
||
|
|
bool ESP8266_EchoResponse = false;
|
||
|
|
bool ESP8266_EchoCommand = false;
|
||
|
|
void UART_OutCharNonBlock(char data){
|
||
|
|
if((TxFifo_Size() >= (TXFIFOSIZE-1))) return;
|
||
|
|
UART_OutChar(data);
|
||
|
|
}
|
||
|
|
// UART receive control/data & transmit FIFOs (see FIFO.h)
|
||
|
|
uint32_t LostData1;
|
||
|
|
// prototypes for private functions
|
||
|
|
void ESP8266TxFifo_Init(void);
|
||
|
|
uint32_t ESP8266TxFifo_Put(char data);
|
||
|
|
uint32_t ESP8266TxFifo_Get(char *datapt);
|
||
|
|
uint32_t ESP8266TxFifo_Size(void);
|
||
|
|
void ESP8266RxFifo_Init(void);
|
||
|
|
uint32_t ESP8266RxFifo_Put(char data);
|
||
|
|
uint32_t ESP8266RxFifo_Get(char *datapt);
|
||
|
|
uint32_t ESP8266RxFifo_Size(void);
|
||
|
|
void ESP8266Rx0Fifo_Init(void);
|
||
|
|
uint32_t ESP8266Rx0Fifo_Put(char data);
|
||
|
|
uint32_t ESP8266Rx0Fifo_Get(char *datapt);
|
||
|
|
uint32_t ESP8266Rx0Fifo_Size(void);
|
||
|
|
|
||
|
|
#define FIFOSIZE 1024 // size of the FIFOs (must be power of 2)
|
||
|
|
#define FIFOSUCCESS 1 // return value on success
|
||
|
|
#define FIFOFAIL 0 // return value on failure
|
||
|
|
|
||
|
|
// ESP8266 state
|
||
|
|
uint16_t ESP8266_Server = 0; // server port, if any
|
||
|
|
uint16_t ESP8266_ConnectionMux = 0;
|
||
|
|
uint16_t ESP8266_Segment = 0; // last segment ID for buffered send
|
||
|
|
|
||
|
|
/*
|
||
|
|
=======================================================================
|
||
|
|
========== helper FUNCTIONS ==========
|
||
|
|
=======================================================================
|
||
|
|
*/
|
||
|
|
|
||
|
|
// make letter lower-case
|
||
|
|
char lc(char letter){
|
||
|
|
if((letter>='A')&&(letter<='Z')) letter |= 0x20;
|
||
|
|
return letter;
|
||
|
|
}
|
||
|
|
// ***** Receive buffer ***
|
||
|
|
#define RECBUFMAX 16
|
||
|
|
char ReceiveSearch[16];
|
||
|
|
uint32_t ReceiveIndex=0;
|
||
|
|
uint32_t ReceiveSize;
|
||
|
|
uint32_t ReceiveMode;
|
||
|
|
void ESP8266_StartReceiveSearch(char *search){
|
||
|
|
ReceiveIndex = 0;
|
||
|
|
int i=0;
|
||
|
|
while(search[i]){
|
||
|
|
ReceiveSearch[i] = search[i];
|
||
|
|
i++;
|
||
|
|
}
|
||
|
|
ReceiveSize = i;
|
||
|
|
ReceiveMode = 1; // searching
|
||
|
|
}
|
||
|
|
char * ESP8266_GetReceiveBuffer(void){
|
||
|
|
if(ReceiveMode==3){
|
||
|
|
return ReceiveSearch;
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
const char ReceiveDataSearchString[]="+IPD,";
|
||
|
|
static uint32_t ReceiveDataSearchIndex = 0;
|
||
|
|
static uint32_t ReceiveDataState = 1; // 0 to disable filtering
|
||
|
|
static uint32_t ReceiveDataStream = 0; // connection ID for received data
|
||
|
|
static uint32_t ReceiveDataLen = 0; // receive data packet remaining size
|
||
|
|
volatile uint32_t ESP8266_DataAvailable = 0; // received data (about to be) available
|
||
|
|
volatile uint32_t ESP8266_DataLoss = 0; // lost data (for debugging)
|
||
|
|
|
||
|
|
//-------------------ReceiveDataFilter -------------------
|
||
|
|
// State machine to filter out received data stream from UART Rx input
|
||
|
|
// Inputs: character to check
|
||
|
|
// Outputs: true if data was filtered out, false otherwise
|
||
|
|
bool ReceiveDataFilter(char letter){
|
||
|
|
switch(ReceiveDataState) { // Filter FSM
|
||
|
|
case 4: // filter out data and put it into the right receive FIFO
|
||
|
|
if(ReceiveDataLen) {
|
||
|
|
switch(ReceiveDataStream) {
|
||
|
|
case 0: if(ESP8266Rx0Fifo_Put(letter) == FIFOFAIL){ // overflow, data loss
|
||
|
|
ESP8266_DataAvailable--;
|
||
|
|
ESP8266_DataLoss++;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
// only one connection currently supported
|
||
|
|
}
|
||
|
|
ReceiveDataLen--;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
ReceiveDataState = 1; // restart
|
||
|
|
// fall through to start searching again if data is done
|
||
|
|
case 1: // Look for +IPD
|
||
|
|
if (letter == ReceiveDataSearchString[ReceiveDataSearchIndex]){ // match letter?
|
||
|
|
ReceiveDataSearchIndex++;
|
||
|
|
if(ReceiveDataSearchString[ReceiveDataSearchIndex] == 0){ // end of match string?
|
||
|
|
if(ESP8266_ConnectionMux) {
|
||
|
|
ReceiveDataState = 2;
|
||
|
|
} else {
|
||
|
|
ReceiveDataState = 3;
|
||
|
|
}
|
||
|
|
ReceiveDataSearchIndex = 0;
|
||
|
|
ReceiveDataStream = 0;
|
||
|
|
ReceiveDataLen = 0;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
ReceiveDataSearchIndex = 0; // start over
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
case 2: // look for connection ID (separated by comma)
|
||
|
|
if(letter >= '0' && letter <= '9') {
|
||
|
|
ReceiveDataStream = ReceiveDataStream * 10 + (letter - '0'); // add digit to ID
|
||
|
|
} else if (letter == ',') {
|
||
|
|
ReceiveDataState = 3; // ID completed, move on
|
||
|
|
} else {
|
||
|
|
ReceiveDataStream = 0;
|
||
|
|
ReceiveDataState = 1; // error, start over
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
case 3: // look for receive data size (separated by colon)
|
||
|
|
if(letter >= '0' && letter <= '9') {
|
||
|
|
ReceiveDataLen = ReceiveDataLen * 10 + (letter - '0'); // add digit to length
|
||
|
|
} else if(letter == ':') {
|
||
|
|
ReceiveDataState = 4; // size complete, move on
|
||
|
|
ESP8266_DataAvailable += ReceiveDataLen; // mark as becoming available
|
||
|
|
} else {
|
||
|
|
ReceiveDataStream = 0;
|
||
|
|
ReceiveDataLen = 0;
|
||
|
|
ReceiveDataState = 1; // error, start over
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
======================================================================
|
||
|
|
========== UART and private FUNCTIONS ==========
|
||
|
|
======================================================================
|
||
|
|
*/
|
||
|
|
|
||
|
|
// Preprocessor magic to construct UARTx_ identifiers
|
||
|
|
#define STR(x) #x
|
||
|
|
#define CONCAT(x,y,z) x ## y ## z
|
||
|
|
|
||
|
|
#define UART_STR(uart) "UART" STR(uart)
|
||
|
|
#define UART_NAME(uart,identifier) CONCAT(UART,uart,identifier)
|
||
|
|
|
||
|
|
#define UART_ESP8266(identifier) UART_NAME(ESP8266_UART,identifier)
|
||
|
|
|
||
|
|
|
||
|
|
// power Domain PD0
|
||
|
|
// for 80MHz bus clock, UART1/UART2 clocks are ULPCLK 40MHz
|
||
|
|
|
||
|
|
//------------------- ESP8266InitUART-------------------
|
||
|
|
// Intializes uart needed to communicate with esp8266
|
||
|
|
// Configure UART for 115200bps operation
|
||
|
|
// Inputs: RX and/or TX echo for debugging
|
||
|
|
// Outputs: none
|
||
|
|
void ESP8266_InitUART(int rx_echo, int tx_echo){
|
||
|
|
ESP8266TxFifo_Init();
|
||
|
|
ESP8266RxFifo_Init();
|
||
|
|
ESP8266Rx0Fifo_Init();
|
||
|
|
ESP8266_EchoResponse = rx_echo;
|
||
|
|
ESP8266_EchoCommand = tx_echo;
|
||
|
|
#if ESP8266_UART==1
|
||
|
|
// do not reset or activate PortA, already done in LaunchPad_Init
|
||
|
|
// RSTCLR to GPIOA and UART1 peripherals
|
||
|
|
// bits 31-24 unlock key 0xB1
|
||
|
|
// bit 1 is Clear reset sticky bit
|
||
|
|
// bit 0 is reset gpio port
|
||
|
|
// GPIOA->GPRCM.RSTCTL = (uint32_t)0xB1000003; // called previously
|
||
|
|
UART1->GPRCM.RSTCTL = 0xB1000003;
|
||
|
|
// Enable power to GPIOA and UART1 peripherals
|
||
|
|
// PWREN
|
||
|
|
// bits 31-24 unlock key 0x26
|
||
|
|
// bit 0 is Enable Power
|
||
|
|
// GPIOA->GPRCM.PWREN = (uint32_t)0x26000001; // called previously
|
||
|
|
UART1->GPRCM.PWREN = 0x26000001;
|
||
|
|
Clock_Delay(24); // time for uart to power up
|
||
|
|
|
||
|
|
// the following code selects which pins to use
|
||
|
|
IOMUX->SECCFG.PINCM[ESP8266_RX] = 0x00040082;
|
||
|
|
//bit 18 INENA input enable
|
||
|
|
//bit 7 PC connected
|
||
|
|
//bits 5-0=2 for UART1_Rx
|
||
|
|
|
||
|
|
// configure alternate UART1 transmit function
|
||
|
|
IOMUX->SECCFG.PINCM[ESP8266_TX] = 0x00000082;
|
||
|
|
//bit 7 PC connected
|
||
|
|
//bits 5-0=2 for UART1_Tx
|
||
|
|
|
||
|
|
UART1->CLKSEL = 0x08; // bus clock
|
||
|
|
UART1->CLKDIV = 0x00; // no divide
|
||
|
|
UART1->CTL0 &= ~0x01; // disable UART1
|
||
|
|
UART1->CTL0 = 0x00020018;
|
||
|
|
// bit 17 FEN=1 enable FIFO
|
||
|
|
// bits 16-15 HSE=00 16x oversampling
|
||
|
|
// bit 14 CTSEN=0 no CTS hardware
|
||
|
|
// bit 13 RTSEN=0 no RTS hardware
|
||
|
|
// bit 12 RTS=0 not RTS
|
||
|
|
// bits 10-8 MODE=000 normal
|
||
|
|
// bits 6-4 TXE=001 enable TxD
|
||
|
|
// bit 3 RXE=1 enable TxD
|
||
|
|
// bit 2 LBE=0 no loop back
|
||
|
|
// bit 0 ENABLE 0 is disable, 1 to enable
|
||
|
|
if(Clock_Freq() == 40000000){
|
||
|
|
// 20000000/16 = 1,250,000 Hz
|
||
|
|
// Baud = 115200
|
||
|
|
// 1,250,000/115200 = 10.8506944444
|
||
|
|
// divider = 10+54/64 = 10.84375
|
||
|
|
UART1->IBRD = 10;
|
||
|
|
UART1->FBRD = 54; // baud =1,250,000/10.84375 = 115,273.77
|
||
|
|
}else if (Clock_Freq() == 32000000){
|
||
|
|
// 32000000/16 = 2,000,000
|
||
|
|
// Baud = 115200
|
||
|
|
// 2,000,000/115200 = 17.3611111
|
||
|
|
// divider = 21+23/64 = 17.359375
|
||
|
|
UART1->IBRD = 17;
|
||
|
|
UART1->FBRD = 23; // 115,211.52
|
||
|
|
}else if (Clock_Freq() == 80000000){
|
||
|
|
// 40000000/16 = 2,500,000 Hz
|
||
|
|
// Baud = 115200
|
||
|
|
// 2,500,000/115200 = 21.701388
|
||
|
|
// divider = 21+45/64 = 21.703125
|
||
|
|
UART1->IBRD = 21;
|
||
|
|
UART1->FBRD = 45; // baud =2,500,000/21.703125 = 115,191
|
||
|
|
}else return;
|
||
|
|
UART1->LCRH = 0x00000030;
|
||
|
|
// bits 5-4 WLEN=11 8 bits
|
||
|
|
// bit 3 STP2=0 1 stop
|
||
|
|
// bit 2 EPS=0 parity select
|
||
|
|
// bit 1 PEN=0 no parity
|
||
|
|
// bit 0 BRK=0 no break
|
||
|
|
UART1->CPU_INT.IMASK = 0x0C01;
|
||
|
|
// bit 11 TXINT yes
|
||
|
|
// bit 10 RXINT yes
|
||
|
|
// bit 0 Receive timeout, yes
|
||
|
|
UART1->IFLS = 0x0422;
|
||
|
|
// bits 11-8 RXTOSEL receiver timeout select 4 (0xF highest)
|
||
|
|
// bits 6-4 RXIFLSEL 2 is greater than or equal to half
|
||
|
|
// bits 2-0 TXIFLSEL 2 is less than or equal to half
|
||
|
|
|
||
|
|
UART1->CTL0 |= 0x01; // enable UART1
|
||
|
|
#else
|
||
|
|
// do not reset or activate PortB, already done in LaunchPad_Init
|
||
|
|
// RSTCLR to GPIOB and UART2 peripherals
|
||
|
|
// bits 31-24 unlock key 0xB1
|
||
|
|
// bit 1 is Clear reset sticky bit
|
||
|
|
// bit 0 is reset gpio port
|
||
|
|
// GPIOB->GPRCM.RSTCTL = (uint32_t)0xB1000003; // called previously
|
||
|
|
UART2->GPRCM.RSTCTL = 0xB1000003;
|
||
|
|
// Enable power to GPIOB and UART2 peripherals
|
||
|
|
// PWREN
|
||
|
|
// bits 31-24 unlock key 0x26
|
||
|
|
// bit 0 is Enable Power
|
||
|
|
// GPIOB->GPRCM.PWREN = (uint32_t)0x26000001; // called previously
|
||
|
|
UART2->GPRCM.PWREN = 0x26000001;
|
||
|
|
Clock_Delay(24); // time for uart to power up
|
||
|
|
|
||
|
|
// the following code selects which pins to use
|
||
|
|
IOMUX->SECCFG.PINCM[ESP8266_RX] = 0x00040082;
|
||
|
|
//bit 18 INENA input enable
|
||
|
|
//bit 7 PC connected
|
||
|
|
//bits 5-0=2 for UART2_Rx
|
||
|
|
|
||
|
|
// configure alternate UART2 transmit function
|
||
|
|
IOMUX->SECCFG.PINCM[ESP8266_TX] = 0x00000082;
|
||
|
|
//bit 7 PC connected
|
||
|
|
//bits 5-0=2 for UART2_Tx
|
||
|
|
|
||
|
|
UART2->CLKSEL = 0x08; // bus clock
|
||
|
|
UART2->CLKDIV = 0x00; // no divide
|
||
|
|
UART2->CTL0 &= ~0x01; // disable UART2
|
||
|
|
UART2->CTL0 = 0x00020018;
|
||
|
|
// bit 17 FEN=1 enable FIFO
|
||
|
|
// bits 16-15 HSE=00 16x oversampling
|
||
|
|
// bit 14 CTSEN=0 no CTS hardware
|
||
|
|
// bit 13 RTSEN=0 no RTS hardware
|
||
|
|
// bit 12 RTS=0 not RTS
|
||
|
|
// bits 10-8 MODE=000 normal
|
||
|
|
// bits 6-4 TXE=001 enable TxD
|
||
|
|
// bit 3 RXE=1 enable TxD
|
||
|
|
// bit 2 LBE=0 no loop back
|
||
|
|
// bit 0 ENABLE 0 is disable, 1 to enable
|
||
|
|
if(Clock_Freq() == 40000000){
|
||
|
|
// 20000000/16 = 1,250,000 Hz
|
||
|
|
// Baud = 115200
|
||
|
|
// 1,250,000/115200 = 10.8506944444
|
||
|
|
// divider = 10+54/64 = 10.84375
|
||
|
|
UART2->IBRD = 10;
|
||
|
|
UART2->FBRD = 54; // baud =1,250,000/10.84375 = 115,273.77
|
||
|
|
}else if (Clock_Freq() == 32000000){
|
||
|
|
// 32000000/16 = 2,000,000
|
||
|
|
// Baud = 115200
|
||
|
|
// 2,000,000/115200 = 17.3611111
|
||
|
|
// divider = 21+23/64 = 17.359375
|
||
|
|
UART2->IBRD = 17;
|
||
|
|
UART2->FBRD = 23; // 115,211.52
|
||
|
|
}else if (Clock_Freq() == 80000000){
|
||
|
|
// 40000000/16 = 2,500,000 Hz
|
||
|
|
// Baud = 115200
|
||
|
|
// 2,500,000/115200 = 21.701388
|
||
|
|
// divider = 21+45/64 = 21.703125
|
||
|
|
UART2->IBRD = 21;
|
||
|
|
UART2->FBRD = 45; // baud =2,500,000/21.703125 = 115,191
|
||
|
|
}else return;
|
||
|
|
UART2->LCRH = 0x00000030;
|
||
|
|
// bits 5-4 WLEN=11 8 bits
|
||
|
|
// bit 3 STP2=0 1 stop
|
||
|
|
// bit 2 EPS=0 parity select
|
||
|
|
// bit 1 PEN=0 no parity
|
||
|
|
// bit 0 BRK=0 no break
|
||
|
|
UART2->CPU_INT.IMASK = 0x0C01;
|
||
|
|
// bit 11 TXINT yes
|
||
|
|
// bit 10 RXINT yes
|
||
|
|
// bit 0 Receive timeout, yes
|
||
|
|
UART2->IFLS = 0x0422;
|
||
|
|
// bits 11-8 RXTOSEL receiver timeout select 4 (0xF highest)
|
||
|
|
// bits 6-4 RXIFLSEL 2 is greater than or equal to half
|
||
|
|
// bits 2-0 TXIFLSEL 2 is less than or equal to half
|
||
|
|
|
||
|
|
UART2->CTL0 |= 0x01; // enable UART2
|
||
|
|
#endif
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
//--------ESP8266_EnableInterrupt--------
|
||
|
|
// Enables uart interrupt
|
||
|
|
// Inputs: none
|
||
|
|
// Outputs: none
|
||
|
|
void ESP8266_EnableInterrupt(void){
|
||
|
|
#if ESP8266_UART==1
|
||
|
|
NVIC->ICPR[0] = 1<<13; // UART1 is IRQ 13
|
||
|
|
NVIC->ISER[0] = 1<<13;
|
||
|
|
NVIC->IP[3] = (NVIC->IP[3]&(~0x0000FF00))|(1<<14); // set priority (bits 15,14) IRQ 13
|
||
|
|
#else
|
||
|
|
NVIC->ICPR[0] = 1<<14; // UART2 is IRQ 14
|
||
|
|
NVIC->ISER[0] = 1<<14;
|
||
|
|
NVIC->IP[3] = (NVIC->IP[3]&(~0x00FF0000))|(1<<22); // set priority (bits 23,22) IRQ 14
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
//--------ESP8266_DisableInterrupt--------
|
||
|
|
// Disables uart interrupt
|
||
|
|
// Inputs: none
|
||
|
|
// Outputs: none
|
||
|
|
void ESP8266_DisableInterrupt(void){
|
||
|
|
#if ESP8266_UART==1
|
||
|
|
NVIC->ICER[0] = 1<<13; // UART1 is IRQ 13
|
||
|
|
#else
|
||
|
|
NVIC->ICER[0] = 1<<14; // UART2 is IRQ 14
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
//----------ESP8266BufferToTx----------
|
||
|
|
// Copies TX buffer (software defined FIFO) to uart
|
||
|
|
// Inputs: none
|
||
|
|
// Outputs:none
|
||
|
|
void static ESP8266BufferToTx(void){
|
||
|
|
char letter;
|
||
|
|
#if ESP8266_UART==1
|
||
|
|
while(((UART1->STAT&0x80) == 0) && (ESP8266TxFifo_Size() > 0)){
|
||
|
|
ESP8266TxFifo_Get(&letter);
|
||
|
|
if(ESP8266_EchoCommand){
|
||
|
|
UART_OutCharNonBlock(letter); // echo
|
||
|
|
}
|
||
|
|
UART1->TXDATA = letter;
|
||
|
|
}
|
||
|
|
#else
|
||
|
|
while(((UART2->STAT&0x80) == 0) && (ESP8266TxFifo_Size() > 0)){
|
||
|
|
ESP8266TxFifo_Get(&letter);
|
||
|
|
if(ESP8266_EchoCommand){
|
||
|
|
UART_OutCharNonBlock(letter); // echo
|
||
|
|
}
|
||
|
|
UART2->TXDATA = letter;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
//----------ESP8266RxToBuffer----------
|
||
|
|
// Copies uart fifo to RX buffer (software defined FIFO)
|
||
|
|
// Inputs: none
|
||
|
|
// Outputs:none
|
||
|
|
void static ESP8266RxToBuffer(void){
|
||
|
|
char letter;
|
||
|
|
#if ESP8266_UART==1
|
||
|
|
while(((UART1->STAT&0x04) == 0)&&((ESP8266RxFifo_Size() < (FIFOSIZE - 1)))){
|
||
|
|
letter = UART1->RXDATA;
|
||
|
|
if(ESP8266_EchoResponse){
|
||
|
|
UART_OutCharNonBlock(letter); // echo
|
||
|
|
if(ReceiveBufferIndex<RECBUFMAX){
|
||
|
|
ReceiveBuffer[ReceiveBufferIndex] = letter;
|
||
|
|
ReceiveBufferIndex++;
|
||
|
|
ReceiveBuffer[ReceiveBufferIndex] = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if(!ReceiveDataFilter(letter)) {
|
||
|
|
ESP8266RxFifo_Put(letter);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
#else
|
||
|
|
while(((UART2->STAT&0x04) == 0)&&((ESP8266RxFifo_Size() < (FIFOSIZE - 1)))){
|
||
|
|
letter = UART2->RXDATA;
|
||
|
|
if(ESP8266_EchoResponse){
|
||
|
|
UART_OutCharNonBlock(letter); // echo
|
||
|
|
if(ReceiveMode==1){// searching
|
||
|
|
if(ReceiveSearch[ReceiveIndex] == letter){
|
||
|
|
ReceiveIndex++;
|
||
|
|
if(ReceiveIndex == ReceiveSize){
|
||
|
|
ReceiveMode=2;
|
||
|
|
}
|
||
|
|
}else{
|
||
|
|
ReceiveIndex = 0; // no match
|
||
|
|
}
|
||
|
|
}else{
|
||
|
|
if(ReceiveMode==2){ // found
|
||
|
|
if(letter>='A'){
|
||
|
|
ReceiveSearch[ReceiveIndex] = letter;
|
||
|
|
ReceiveIndex++;
|
||
|
|
}else{
|
||
|
|
ReceiveMode = 3; // done
|
||
|
|
ReceiveSearch[ReceiveIndex] = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if(!ReceiveDataFilter(letter)) {
|
||
|
|
ESP8266RxFifo_Put(letter);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
//----------UART_Handler----------
|
||
|
|
// At least one of three things has happened:
|
||
|
|
// hardware TX FIFO goes from 3 to 2 or less items
|
||
|
|
// hardware RX FIFO goes from 1 to 2 or more items
|
||
|
|
// UART receiver has timed out
|
||
|
|
#if ESP8266_UART==1
|
||
|
|
void UART1_IRQHandler(void){ uint32_t status;
|
||
|
|
status = UART1->CPU_INT.IIDX; // reading clears bit in RIS
|
||
|
|
if(status == 0x01){ // 0x01 receive timeout
|
||
|
|
ESP8266RxToBuffer();
|
||
|
|
}else if(status == 0x0B){ // 0x0B receive
|
||
|
|
ESP8266RxToBuffer();
|
||
|
|
}else if(status == 0x0C){ // 0x0C transmit
|
||
|
|
ESP8266BufferToTx();
|
||
|
|
if(ESP8266TxFifo_Size() == 0){ // software TX FIFO is empty
|
||
|
|
UART1->CPU_INT.IMASK &= ~0x0800; // disable TX FIFO interrupt
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
#else
|
||
|
|
void UART2_IRQHandler(void){ uint32_t status;
|
||
|
|
status = UART2->CPU_INT.IIDX; // reading clears bit in RIS
|
||
|
|
if(status == 0x01){ // 0x01 receive timeout
|
||
|
|
ESP8266RxToBuffer();
|
||
|
|
}else if(status == 0x0B){ // 0x0B receive
|
||
|
|
ESP8266RxToBuffer();
|
||
|
|
}else if(status == 0x0C){ // 0x0C transmit
|
||
|
|
ESP8266BufferToTx();
|
||
|
|
if(ESP8266TxFifo_Size() == 0){ // software TX FIFO is empty
|
||
|
|
UART2->CPU_INT.IMASK &= ~0x0800; // disable TX FIFO interrupt
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
|
||
|
|
//--------ESP8266_OutChar--------
|
||
|
|
// Prints a character to the esp8226 via uart
|
||
|
|
// Inputs: character to transmit
|
||
|
|
// Outputs: none
|
||
|
|
void ESP8266_OutChar(char data){
|
||
|
|
ESP8266TxFifo_Put(data); // blocks via semaphore if FIFO full
|
||
|
|
#if ESP8266_UART==1
|
||
|
|
UART1->CPU_INT.IMASK &= ~0x0800; // disarm TX FIFO interrupt
|
||
|
|
ESP8266BufferToTx();
|
||
|
|
UART1->CPU_INT.IMASK |= 0x0800; // rearm TX FIFO interrupt
|
||
|
|
#else
|
||
|
|
UART2->CPU_INT.IMASK &= ~0x0800; // disarm TX FIFO interrupt
|
||
|
|
ESP8266BufferToTx();
|
||
|
|
UART2->CPU_INT.IMASK |= 0x0800; // rearm TX FIFO interrupt
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
//--------ESP8266_InChar--------
|
||
|
|
// Read a character from the esp8226 via uart
|
||
|
|
// Inputs: none
|
||
|
|
// Outputs: character received
|
||
|
|
char ESP8266_InChar(void){ char letter;
|
||
|
|
ESP8266RxFifo_Get(&letter); // blocks via semaphore if FIFO empty
|
||
|
|
return(letter);
|
||
|
|
}
|
||
|
|
|
||
|
|
//---------ESP8266_SendCommand-----
|
||
|
|
// Sends a string to the esp8266 module
|
||
|
|
// Inputs: string to send (null-terminated)
|
||
|
|
// Outputs: none
|
||
|
|
void ESP8266_SendCommand(const char* command){
|
||
|
|
int index = 0;
|
||
|
|
while(command[index] != 0){
|
||
|
|
ESP8266_OutChar(command[index++]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//---------ESP8266_WaitForResponse-----
|
||
|
|
// Busy-wait until response found
|
||
|
|
// Inputs: Success or failure strings to search for
|
||
|
|
// Outputs: 1 on success, 0 on failure
|
||
|
|
int ESP8266_WaitForResponse(const char *success, const char* failure) {
|
||
|
|
char d;
|
||
|
|
const char *s = success;
|
||
|
|
const char *f = failure;
|
||
|
|
while((!s || *s) && (!f || *f)) { // end of search string reached?
|
||
|
|
d = ESP8266_InChar();
|
||
|
|
if(s && (d == *s)) {
|
||
|
|
s++;
|
||
|
|
} else {
|
||
|
|
s = success; // start over
|
||
|
|
if(s && (d == *s)) s++; // match first char?
|
||
|
|
}
|
||
|
|
if(f && (d == *f)) {
|
||
|
|
f++;
|
||
|
|
} else {
|
||
|
|
f = failure; // start over
|
||
|
|
if(f && (d == *f)) f++; // match first char?
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if(failure && !(*f)) return FAILURE;
|
||
|
|
return SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
=======================================================================
|
||
|
|
========== ESP8266 PUBLIC FUNCTIONS ==========
|
||
|
|
=======================================================================
|
||
|
|
*/
|
||
|
|
|
||
|
|
//-------------------ESP8266_Init --------------
|
||
|
|
// Initializes the module
|
||
|
|
// Inputs: RX and/or TX echo for debugging
|
||
|
|
// Outputs: 1 for success, 0 for failure (no ESP detected)
|
||
|
|
int ESP8266_Init(int rx_echo, int tx_echo){ char c; const char* s; uint32_t timer = 1;
|
||
|
|
// Disable interrupt during initialization
|
||
|
|
ESP8266_DisableInterrupt();
|
||
|
|
|
||
|
|
// Initialize UART to communicate with ESP
|
||
|
|
ESP8266_InitUART(rx_echo, tx_echo);
|
||
|
|
|
||
|
|
// Initialize reset port on PA25
|
||
|
|
IOMUX->SECCFG.PINCM[PA25INDEX] = (uint32_t) 0x00000081;
|
||
|
|
GPIOA->DOE31_0 |= (1<<25);
|
||
|
|
|
||
|
|
// Hardware reset
|
||
|
|
GPIOA->DOUTCLR31_0 = (1<<25); // reset low
|
||
|
|
Clock_Delay1ms(10);
|
||
|
|
GPIOA->DOUTSET31_0 = (1<<25); // reset high
|
||
|
|
|
||
|
|
// Wait for ready status with timeout
|
||
|
|
// Use low-level UART communication, interrupts disabled
|
||
|
|
s = ESP8266_READY_RESPONSE;
|
||
|
|
timer = 5000000; // around a 1-2s total timeout
|
||
|
|
while(*s) {
|
||
|
|
#if ESP8266_UART==1
|
||
|
|
while(timer && ((UART1->STAT&0x04) == 0x04)) { timer--; }
|
||
|
|
if(!timer) break;
|
||
|
|
c = (char)UART1->RXDATA;
|
||
|
|
#else
|
||
|
|
while(timer && ((UART2->STAT&0x04) == 0x04)) { timer--; }
|
||
|
|
if(!timer) break;
|
||
|
|
c = (char)UART2->RXDATA;
|
||
|
|
#endif
|
||
|
|
if(rx_echo) UART_OutCharNonBlock(c); // echo, requires UART0 to be operational, will print garbage
|
||
|
|
if(c == *s) {
|
||
|
|
s++;
|
||
|
|
} else {
|
||
|
|
s = ESP8266_READY_RESPONSE;
|
||
|
|
if(c == *s) s++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Finally enable interrupt
|
||
|
|
ESP8266_EnableInterrupt();
|
||
|
|
|
||
|
|
if(!timer) return FAILURE;
|
||
|
|
return SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
//-------------------ESP8266_Connect --------------
|
||
|
|
// Bring interface up and connect to Wifi
|
||
|
|
// Inputs: enable debug output
|
||
|
|
// Outputs: 1 on success, 0 on failure
|
||
|
|
int ESP8266_Connect(int verbose){
|
||
|
|
if(ESP8266_Reset()==FAILURE) return FAILURE;
|
||
|
|
|
||
|
|
if(verbose) // debug output: MAC address oF ESP8266
|
||
|
|
ESP8266_GetMACAddress();
|
||
|
|
|
||
|
|
#if SOFTAP
|
||
|
|
if(ESP8266_SoftAccessPoint(SSID_NAME,PASSKEY)==FAILURE) return FAILURE;
|
||
|
|
if(ESP8266_SetWifiMode(ESP8266_WIFI_MODE_AP)==FAILURE) return FAILURE;
|
||
|
|
#else
|
||
|
|
if(ESP8266_SetWifiMode(ESP8266_WIFI_MODE_CLIENT)==FAILURE) return FAILURE;
|
||
|
|
|
||
|
|
if(verbose) // debug output: see APs in area
|
||
|
|
ESP8266_ListAccessPoints();
|
||
|
|
|
||
|
|
if(ESP8266_JoinAccessPoint(SSID_NAME,PASSKEY)==FAILURE) return FAILURE;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if(verbose) // debug output: our IP address
|
||
|
|
ESP8266_GetIPAddress();
|
||
|
|
|
||
|
|
return SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
//-------------------ESP8266_StartServer --------------
|
||
|
|
// Start server on specific port
|
||
|
|
// Inputs: port and server timeout
|
||
|
|
// Outputs: 1 on success, 0 on failure
|
||
|
|
int ESP8266_StartServer(uint16_t port, uint16_t timeout){
|
||
|
|
if(ESP8266_SetConnectionMux(1)==FAILURE) return FAILURE;
|
||
|
|
if(ESP8266_EnableServer(port)==FAILURE) return FAILURE;
|
||
|
|
if(ESP8266_SetServerTimeout(timeout)==FAILURE) return FAILURE;
|
||
|
|
return SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
//-------------------ESP8266_StopServer --------------
|
||
|
|
// Stop server and set to single-client mode
|
||
|
|
// Inputs: none
|
||
|
|
// Outputs: 1 on success, 0 on failure
|
||
|
|
int ESP8266_StopServer(void){
|
||
|
|
if(ESP8266_DisableServer()==FAILURE) return FAILURE;
|
||
|
|
if(ESP8266_SetConnectionMux(0)==FAILURE) return FAILURE;
|
||
|
|
return SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
//----------ESP8266_Reset------------
|
||
|
|
// Soft resets the esp8266 module
|
||
|
|
// Input: none
|
||
|
|
// Output: 1 if success, 0 if fail
|
||
|
|
int ESP8266_Reset(void){ int try=MAXTRY;
|
||
|
|
while(try){
|
||
|
|
ESP8266_SendCommand("AT+RST\r\n");
|
||
|
|
if(ESP8266_WaitForResponse(ESP8266_READY_RESPONSE,0)) return SUCCESS;
|
||
|
|
try--;
|
||
|
|
}
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
//---------ESP8266_Restore-----
|
||
|
|
// Restore the ESP8266 module to default values
|
||
|
|
// Inputs: none
|
||
|
|
// Outputs: 1 if success, 0 if fail
|
||
|
|
int ESP8266_Restore(void) { int try=MAXTRY;
|
||
|
|
while(try){
|
||
|
|
ESP8266_SendCommand("AT+RESTORE\r\n");
|
||
|
|
if(ESP8266_WaitForResponse(ESP8266_READY_RESPONSE,0)) return SUCCESS;
|
||
|
|
try--;
|
||
|
|
}
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
//---------ESP8266_GetVersionNumber----------
|
||
|
|
// Get status
|
||
|
|
// Input: none
|
||
|
|
// Output: 1 if success, 0 if fail
|
||
|
|
int ESP8266_GetVersionNumber(void){ int try=MAXTRY;
|
||
|
|
while(try){
|
||
|
|
ESP8266_SendCommand("AT+GMR\r\n");
|
||
|
|
if(ESP8266_WaitForResponse(ESP8266_OK_RESPONSE,0)) return SUCCESS;
|
||
|
|
try--;
|
||
|
|
}
|
||
|
|
return FAILURE; // fail
|
||
|
|
}
|
||
|
|
|
||
|
|
//---------ESP8266_GetMACAddress----------
|
||
|
|
// Get MAC address
|
||
|
|
// Input: none
|
||
|
|
// Output: 1 if success, 0 if fail
|
||
|
|
int ESP8266_GetMACAddress(void){ int try=MAXTRY;
|
||
|
|
while(try){
|
||
|
|
ESP8266_SendCommand("AT+CIPSTAMAC?\r\n");
|
||
|
|
if(ESP8266_WaitForResponse(ESP8266_OK_RESPONSE,0)) return SUCCESS;
|
||
|
|
try--;
|
||
|
|
}
|
||
|
|
return FAILURE; // fail
|
||
|
|
}
|
||
|
|
|
||
|
|
//---------ESP8266_SetWifiMode----------
|
||
|
|
// Configures the esp8266 to operate as a wifi client, access point, or both
|
||
|
|
// Input: mode accepts ESP8266_WIFI_MODE constants
|
||
|
|
// Output: 1 if success, 0 if fail
|
||
|
|
int ESP8266_SetWifiMode(uint8_t mode){ int try=MAXTRY;
|
||
|
|
char TXBuffer[32];
|
||
|
|
while(try){
|
||
|
|
sprintf(TXBuffer, "AT+CWMODE=%d\r\n", mode);
|
||
|
|
ESP8266_SendCommand(TXBuffer);
|
||
|
|
if(ESP8266_WaitForResponse(ESP8266_OK_RESPONSE,0)) return SUCCESS;
|
||
|
|
try--;
|
||
|
|
}
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
//---------ESP8266_SetConnectionMux----------
|
||
|
|
// Enables the esp8266 connection mux, required for starting tcp server
|
||
|
|
// Input: 0 (single) or 1 (multiple)
|
||
|
|
// Output: 1 if success, 0 if fail
|
||
|
|
int ESP8266_SetConnectionMux(uint8_t enabled){ int try=MAXTRY;
|
||
|
|
//char TXBuffer[32];
|
||
|
|
while(try){
|
||
|
|
if(enabled){
|
||
|
|
//sprintf(TXBuffer, "AT+CIPMUX=%d\r\n", enabled);
|
||
|
|
ESP8266_SendCommand("AT+CIPMUX=1\r\n");
|
||
|
|
}else{
|
||
|
|
ESP8266_SendCommand("AT+CIPMUX=0\r\n");
|
||
|
|
|
||
|
|
}
|
||
|
|
if(ESP8266_WaitForResponse(ESP8266_OK_RESPONSE,0)) {
|
||
|
|
ESP8266_ConnectionMux = enabled;
|
||
|
|
return SUCCESS;
|
||
|
|
}
|
||
|
|
try--;
|
||
|
|
}
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
//---------ESP8266_ListAccessPoints----------
|
||
|
|
// Lists available wifi access points
|
||
|
|
// Input: none
|
||
|
|
// Output: 1 if success, 0 if fail
|
||
|
|
int ESP8266_ListAccessPoints(void){ int try=MAXTRY;
|
||
|
|
while(try){
|
||
|
|
ESP8266_SendCommand("AT+CWLAP\r\n");
|
||
|
|
if(ESP8266_WaitForResponse(ESP8266_OK_RESPONSE,ESP8266_ERROR_RESPONSE)) return SUCCESS;
|
||
|
|
try--;
|
||
|
|
}
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
//----------ESP8266_JoinAccessPoint------------
|
||
|
|
// Joins a wifi access point using specified ssid and password
|
||
|
|
// Input: SSID and PASSWORD
|
||
|
|
// Output: 1 if success, 0 if fail
|
||
|
|
int ESP8266_JoinAccessPoint(const char* ssid, const char* password){ int try=MAXTRY;
|
||
|
|
while(try){
|
||
|
|
ESP8266_SendCommand("AT+CWJAP=\"");
|
||
|
|
ESP8266_SendCommand(ssid);
|
||
|
|
ESP8266_SendCommand("\",\"");
|
||
|
|
ESP8266_SendCommand(password);
|
||
|
|
ESP8266_SendCommand("\"\r\n");
|
||
|
|
if(ESP8266_WaitForResponse(ESP8266_OK_RESPONSE,ESP8266_FAIL_RESPONSE)) return SUCCESS;
|
||
|
|
try--;
|
||
|
|
}
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ----------ESP8266_QuitAccessPoint-------------
|
||
|
|
// Disconnects from currently connected wifi access point
|
||
|
|
// Inputs: none
|
||
|
|
// Outputs: 1 if success, 0 if fail
|
||
|
|
int ESP8266_QuitAccessPoint(void){ int try=MAXTRY;
|
||
|
|
while(try){
|
||
|
|
ESP8266_SendCommand("AT+CWQAP\r\n");
|
||
|
|
if(ESP8266_WaitForResponse(ESP8266_OK_RESPONSE,0)) return SUCCESS;
|
||
|
|
try--;
|
||
|
|
}
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
//----------ESP8266_ConfigureAccessPoint------------
|
||
|
|
// Configures esp8266 wifi soft access point settings
|
||
|
|
// Use this function only when in AP mode (and not in client mode)
|
||
|
|
// Input: SSID, Password, channel, security
|
||
|
|
// Output: 1 if success, 0 if fail
|
||
|
|
int ESP8266_ConfigureAccessPoint(const char* ssid, const char* password, uint8_t channel, uint8_t encryptMode){
|
||
|
|
int try=MAXTRY;
|
||
|
|
char TXBuffer[32];
|
||
|
|
while(try){
|
||
|
|
ESP8266_SendCommand("AT+CWSAP=\"");
|
||
|
|
ESP8266_SendCommand(ssid);
|
||
|
|
ESP8266_SendCommand("\",\"");
|
||
|
|
ESP8266_SendCommand(password);
|
||
|
|
sprintf(TXBuffer, "\",%d,%d\r\n", channel, encryptMode);
|
||
|
|
ESP8266_SendCommand(TXBuffer);
|
||
|
|
if(ESP8266_WaitForResponse(ESP8266_OK_RESPONSE,ESP8266_ERROR_RESPONSE)) return SUCCESS;
|
||
|
|
try--;
|
||
|
|
}
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
//---------ESP8266_GetIPAddress----------
|
||
|
|
// Get local IP address
|
||
|
|
// Input: none
|
||
|
|
// Output: 1 if success, 0 if fail
|
||
|
|
int ESP8266_GetIPAddress(void){ int try=MAXTRY;
|
||
|
|
while(try){
|
||
|
|
ESP8266_SendCommand("AT+CIFSR\r\n");
|
||
|
|
if(ESP8266_WaitForResponse(ESP8266_OK_RESPONSE,ESP8266_ERROR_RESPONSE)) return SUCCESS;
|
||
|
|
try--;
|
||
|
|
}
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
//---------ESP8266_SetSSLClientConfiguration----------
|
||
|
|
// Set SSL client configuration
|
||
|
|
// Requires certificates to be flashed into the ESP firmware
|
||
|
|
// Inputs: enable/disable client/server certificate checks
|
||
|
|
// output: 1 if success, 0 if fail
|
||
|
|
int ESP8266_SetSSLClientConfiguration(int verifyClient, int verifyServer){ int try=MAXTRY;
|
||
|
|
char TXBuffer[32];
|
||
|
|
while(try){
|
||
|
|
sprintf(TXBuffer, "AT+CIPSSLCCONF=%d\r\n", (verifyClient? 1 : 0) + (verifyServer? 2 : 0));
|
||
|
|
ESP8266_SendCommand(TXBuffer);
|
||
|
|
if(ESP8266_WaitForResponse(ESP8266_OK_RESPONSE,ESP8266_ERROR_RESPONSE)) return SUCCESS;
|
||
|
|
try--;
|
||
|
|
}
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
//---------ESP8266_SetSSLBufferSize----------
|
||
|
|
// Set SSL buffer size
|
||
|
|
// Inputs: buffer size between 2048 and 4096
|
||
|
|
// output: 1 if success, 0 if fail
|
||
|
|
int ESP8266_SetSSLBufferSize(uint16_t bufferSize){ int try=MAXTRY;
|
||
|
|
char TXBuffer[32];
|
||
|
|
while(try){
|
||
|
|
sprintf(TXBuffer, "AT+CIPSSLSIZE=%d\r\n", bufferSize);
|
||
|
|
ESP8266_SendCommand(TXBuffer);
|
||
|
|
if(ESP8266_WaitForResponse(ESP8266_OK_RESPONSE,ESP8266_ERROR_RESPONSE)) return SUCCESS;
|
||
|
|
try--;
|
||
|
|
}
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
//---------ESP8266_MakeTCPConnection----------
|
||
|
|
// Establish TCP or SSL connection
|
||
|
|
// The ESP only seems to have limited SSL support, does not work with all servers
|
||
|
|
// Inputs: IP address or web page as a string, port, and keepalive time (0 if none)
|
||
|
|
// output: 1 if success, 0 if fail
|
||
|
|
int ESP8266_MakeTCPConnection(char *IPaddress, uint16_t port, uint16_t keepalive, int ssl){ int try=MAXTRY;
|
||
|
|
char TXBuffer[32];
|
||
|
|
while(try){
|
||
|
|
if(ssl){
|
||
|
|
ESP8266_SendCommand("AT+CIPSTART=\"SSL\",\"");
|
||
|
|
} else {
|
||
|
|
ESP8266_SendCommand("AT+CIPSTART=\"TCP\",\"");
|
||
|
|
}
|
||
|
|
ESP8266_SendCommand(IPaddress);
|
||
|
|
if(keepalive) {
|
||
|
|
sprintf(TXBuffer, "\",%d,%d\r\n", port, keepalive);
|
||
|
|
} else {
|
||
|
|
sprintf(TXBuffer, "\",%d\r\n", port);
|
||
|
|
}
|
||
|
|
ESP8266_SendCommand(TXBuffer); // open and connect to a socket
|
||
|
|
if(ESP8266_WaitForResponse(ESP8266_OK_RESPONSE,ESP8266_ERROR_RESPONSE)) return SUCCESS;
|
||
|
|
try--;
|
||
|
|
}
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
//---------ESP8266_Send----------
|
||
|
|
// Send a string to server
|
||
|
|
// Input: payload to send
|
||
|
|
// Output: 1 if success, 0 if fail
|
||
|
|
int ESP8266_Send(const char* fetch){
|
||
|
|
char TXBuffer[32];
|
||
|
|
if(ESP8266_ConnectionMux) {
|
||
|
|
sprintf(TXBuffer, "AT+CIPSEND=%d,%d\r\n", 0, strlen(fetch));
|
||
|
|
} else {
|
||
|
|
sprintf(TXBuffer, "AT+CIPSEND=%d\r\n", strlen(fetch));
|
||
|
|
}
|
||
|
|
ESP8266_SendCommand(TXBuffer);
|
||
|
|
if(!ESP8266_WaitForResponse(">",ESP8266_ERROR_RESPONSE)) return FAILURE;
|
||
|
|
ESP8266_SendCommand(fetch);
|
||
|
|
if(ESP8266_WaitForResponse(ESP8266_SENDOK_RESPONSE,ESP8266_ERROR_RESPONSE)) return SUCCESS;
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
//---------ESP8266_SendBuffered----------
|
||
|
|
// Send a string to server using ESP TCP-send buffer
|
||
|
|
// Input: payload to send
|
||
|
|
// Output: 1 if success, 0 if fail
|
||
|
|
int ESP8266_SendBuffered(const char* fetch){
|
||
|
|
char TXBuffer[32];
|
||
|
|
if(ESP8266_ConnectionMux) {
|
||
|
|
sprintf(TXBuffer, "AT+CIPSENDBUF=%d,%d\r\n", 0, strlen(fetch));
|
||
|
|
} else {
|
||
|
|
sprintf(TXBuffer, "AT+CIPSENDBUF=%d\r\n", strlen(fetch));
|
||
|
|
}
|
||
|
|
ESP8266_SendCommand(TXBuffer);
|
||
|
|
if(!ESP8266_WaitForResponse(">",ESP8266_ERROR_RESPONSE)) return FAILURE;
|
||
|
|
ESP8266_Segment++;
|
||
|
|
ESP8266_SendCommand(fetch);
|
||
|
|
sprintf(TXBuffer, "Recv %d bytes", strlen(fetch));
|
||
|
|
if(ESP8266_WaitForResponse(TXBuffer,ESP8266_ERROR_RESPONSE)) return SUCCESS;
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
//---------ESP8266_SendBufferedStatus----------
|
||
|
|
// Check status of last buffered segment
|
||
|
|
// Input: none
|
||
|
|
// Output: 1 if success, 0 if fail
|
||
|
|
int ESP8266_SendBufferedStatus(void){
|
||
|
|
char OKBuffer[16];
|
||
|
|
char FailBuffer[24];
|
||
|
|
if(ESP8266_ConnectionMux) {
|
||
|
|
sprintf(OKBuffer, "\n%d,%d,SEND OK\r\n", 0, ESP8266_Segment);
|
||
|
|
sprintf(FailBuffer, "\n%d,%d,SEND FAIL\r\n", 0, ESP8266_Segment);
|
||
|
|
} else {
|
||
|
|
sprintf(OKBuffer, "\n%d,SEND OK\r\n", ESP8266_Segment);
|
||
|
|
sprintf(FailBuffer, "\n%d,SEND FAIL\r\n", ESP8266_Segment);
|
||
|
|
}
|
||
|
|
if(ESP8266_WaitForResponse(OKBuffer,FailBuffer)) return SUCCESS;
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
//---------ESP8266_Receive----------
|
||
|
|
// Receive a string from server
|
||
|
|
// Reads from data input until end of line or max length is reached
|
||
|
|
// Input: buffer and max length
|
||
|
|
// Output: 1 and null-terminated string if success, 0 if fail (disconnected)
|
||
|
|
int ESP8266_Receive(char* fetch, uint32_t max){ long sr; const char* s;
|
||
|
|
char letter;
|
||
|
|
while(max > 1) {
|
||
|
|
if(ESP8266Rx0Fifo_Size() || ESP8266_DataAvailable) { // data (about to be) available?
|
||
|
|
ESP8266Rx0Fifo_Get(&letter); // blocks via semaphore if FIFO empty
|
||
|
|
// ESP8266_DisableInterrupt(); // critical section
|
||
|
|
sr = StartCritical();
|
||
|
|
if(ESP8266_DataAvailable) ESP8266_DataAvailable--;
|
||
|
|
EndCritical(sr);
|
||
|
|
// ESP8266_EnableInterrupt();
|
||
|
|
if(letter == '\r') continue;
|
||
|
|
if(letter == '\n') break;
|
||
|
|
*fetch = letter;
|
||
|
|
fetch++;
|
||
|
|
max--;
|
||
|
|
} else { // wait for next packet or connection close
|
||
|
|
if(ESP8266_ConnectionMux) {
|
||
|
|
s = "0,CLOSED";
|
||
|
|
} else {
|
||
|
|
s = "CLOSED";
|
||
|
|
}
|
||
|
|
if(!ESP8266_WaitForResponse(ReceiveDataSearchString,s)){
|
||
|
|
*fetch = 0; // connection closed
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
while(ESP8266_InChar() != ':') {} // wait for DataAvailable to be updated
|
||
|
|
}
|
||
|
|
}
|
||
|
|
*fetch = 0; // terminate with null character
|
||
|
|
return SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
//---------ESP8266_CloseTCPConnection----------
|
||
|
|
// Close TCP connection
|
||
|
|
// Input: none
|
||
|
|
// Output: 1 if success, 0 if fail
|
||
|
|
int ESP8266_CloseTCPConnection(void){ int try=MAXTRY;
|
||
|
|
while(try){
|
||
|
|
if(ESP8266_ConnectionMux) {
|
||
|
|
ESP8266_SendCommand("AT+CIPCLOSE=0\r\n");
|
||
|
|
} else {
|
||
|
|
ESP8266_SendCommand("AT+CIPCLOSE\r\n");
|
||
|
|
}
|
||
|
|
if(ESP8266_WaitForResponse(ESP8266_OK_RESPONSE,ESP8266_ERROR_RESPONSE)) {
|
||
|
|
ESP8266Rx0Fifo_Init(); // Discard any data
|
||
|
|
return SUCCESS;
|
||
|
|
}
|
||
|
|
try--;
|
||
|
|
}
|
||
|
|
ESP8266Rx0Fifo_Init(); // Discard any data
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
//---------ESP8266_SetDataTransmissionMode----------
|
||
|
|
// Set data transmission passthrough mode
|
||
|
|
// Input: 0 not data mode, 1 data mode; return "Link is builded"
|
||
|
|
// Output: 1 if success, 0 if fail
|
||
|
|
int ESP8266_SetDataTransmissionMode(uint8_t mode){ int try=MAXTRY;
|
||
|
|
char TXBuffer[32];
|
||
|
|
while(try){
|
||
|
|
sprintf(TXBuffer, "AT+CIPMODE=%d\r\n", mode);
|
||
|
|
ESP8266_SendCommand(TXBuffer);
|
||
|
|
if(ESP8266_WaitForResponse(ESP8266_OK_RESPONSE,0)) return SUCCESS;
|
||
|
|
try--;
|
||
|
|
}
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
//---------ESP8266_GetStatus----------
|
||
|
|
// Get network connection status
|
||
|
|
// Input: none
|
||
|
|
// Output: 1 if success, 0 if fail
|
||
|
|
int ESP8266_GetStatus(void){ int try=MAXTRY;
|
||
|
|
while(try){
|
||
|
|
ESP8266_SendCommand("AT+CIPSTATUS\r\n");
|
||
|
|
if(ESP8266_WaitForResponse(ESP8266_OK_RESPONSE,0)) return SUCCESS;
|
||
|
|
try--;
|
||
|
|
}
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
// --------ESP8266_EnableServer------------------
|
||
|
|
// Enables tcp server on specified port
|
||
|
|
// Inputs: port number
|
||
|
|
// Outputs: 1 if success, 0 if fail
|
||
|
|
int ESP8266_EnableServer(uint16_t port){ int try=MAXTRY;
|
||
|
|
char TXBuffer[32];
|
||
|
|
while(try){
|
||
|
|
sprintf(TXBuffer, "AT+CIPSERVER=1,%d\r\n", port);
|
||
|
|
ESP8266_SendCommand(TXBuffer);
|
||
|
|
if(ESP8266_WaitForResponse(ESP8266_OK_RESPONSE,0)) {
|
||
|
|
ESP8266_Server = port;
|
||
|
|
return SUCCESS;
|
||
|
|
}
|
||
|
|
try--;
|
||
|
|
}
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ----------ESP8266_SetServerTimeout--------------
|
||
|
|
// Set connection timeout for tcp server, 0-28800 seconds
|
||
|
|
// Inputs: timeout parameter
|
||
|
|
// Outputs: 1 if success, 0 if fail
|
||
|
|
int ESP8266_SetServerTimeout(uint16_t timeout){ int try=MAXTRY;
|
||
|
|
char TXBuffer[32];
|
||
|
|
while(try){
|
||
|
|
sprintf(TXBuffer, "AT+CIPSTO=%d\r\n", timeout);
|
||
|
|
ESP8266_SendCommand(TXBuffer);
|
||
|
|
if(ESP8266_WaitForResponse(ESP8266_OK_RESPONSE,ESP8266_ERROR_RESPONSE)) return SUCCESS;
|
||
|
|
try--;
|
||
|
|
}
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ----------ESP8266_WaitForConnection--------------
|
||
|
|
// Wait for incoming connection on server
|
||
|
|
// must ensure that no other ESP calls are done while waiting
|
||
|
|
// this should really be done in the background interrupt handler
|
||
|
|
// using a mailbox to communicate with this function
|
||
|
|
// Inputs: none
|
||
|
|
// Outputs: 1 if success, 0 if fail
|
||
|
|
int ESP8266_WaitForConnection(void){
|
||
|
|
if(!ESP8266_ConnectionMux) return FAILURE;
|
||
|
|
if(!ESP8266_Server) return FAILURE;
|
||
|
|
if(ESP8266_WaitForResponse("0,CONNECT\r\n",0)) return SUCCESS;
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
//---------ESP8266_DisableServer----------
|
||
|
|
// Disables tcp server
|
||
|
|
// Input: none
|
||
|
|
// Output: 1 if success, 0 if fail
|
||
|
|
int ESP8266_DisableServer(void){ int try=MAXTRY;
|
||
|
|
while(try){
|
||
|
|
ESP8266_SendCommand("AT+CIPSERVER=0\r\n");
|
||
|
|
if(ESP8266_WaitForResponse(ESP8266_OK_RESPONSE,0)) {
|
||
|
|
ESP8266_Server = 0;
|
||
|
|
return SUCCESS;
|
||
|
|
}
|
||
|
|
try--;
|
||
|
|
}
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Declare state variables for FiFo
|
||
|
|
// size, buffer, put and get indexes
|
||
|
|
// Lab 6 change: Added semaphores for OS synchronization.
|
||
|
|
// TxFifo: foreground threads Put (block if full), ISR Gets (signals space available)
|
||
|
|
// RxFifo: ISR Puts (signals data available), foreground threads Get (block if empty)
|
||
|
|
// Rx0Fifo: ISR Puts (signals data available), foreground threads Get (block if empty)
|
||
|
|
int32_t static ESP8266TxPutI; // Index to put new
|
||
|
|
int32_t static ESP8266TxGetI; // Index of oldest
|
||
|
|
char static ESP8266TxFifo[FIFOSIZE];
|
||
|
|
Sema4_t ESP8266TxSpaceAvailable; // Lab 6: counting semaphore for free space
|
||
|
|
|
||
|
|
// *********** ESP8266TxFifo_Init**********
|
||
|
|
// Initializes a software ESP8266TxFIFO of a
|
||
|
|
// fixed size and sets up indexes for
|
||
|
|
// put and get operations
|
||
|
|
// Lab 6 change: Also initializes TxSpaceAvailable semaphore to FIFOSIZE-1
|
||
|
|
void ESP8266TxFifo_Init(void){
|
||
|
|
ESP8266TxPutI = ESP8266TxGetI = 0;
|
||
|
|
OS_InitSemaphore(&ESP8266TxSpaceAvailable, FIFOSIZE-1);
|
||
|
|
}
|
||
|
|
|
||
|
|
// *********** ESP8266TxFifo_Put**********
|
||
|
|
// Adds an element to the ESP8266TxFIFO
|
||
|
|
// Input: data is character to be inserted
|
||
|
|
// Output: 1 for success, data properly saved
|
||
|
|
// 0 for failure, TxFIFO is full
|
||
|
|
// Lab 6 change: Now blocks via OS_Wait if FIFO is full (called by foreground thread)
|
||
|
|
uint32_t ESP8266TxFifo_Put(char data){
|
||
|
|
OS_Wait(&ESP8266TxSpaceAvailable);
|
||
|
|
ESP8266TxFifo[ESP8266TxPutI] = data;
|
||
|
|
ESP8266TxPutI = (ESP8266TxPutI+1)&(FIFOSIZE-1);
|
||
|
|
return SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
// *********** ESP8266TxFifo_Get**********
|
||
|
|
// Gets an element from the ESP8266TxFIFO
|
||
|
|
// Input: pointer to empty 8-bit variable
|
||
|
|
// Output: If the ESP8266TxFIFO is empty return 0
|
||
|
|
// If the ESP8266TxFIFO has data, remove it, and put in *datapt, return 1
|
||
|
|
// Lab 6 change: Calls OS_Signal after removing element to wake blocked Put callers (called by ISR)
|
||
|
|
uint32_t ESP8266TxFifo_Get(char *datapt){
|
||
|
|
if(ESP8266TxGetI == ESP8266TxPutI){
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
*datapt = ESP8266TxFifo[ESP8266TxGetI];
|
||
|
|
ESP8266TxGetI = (ESP8266TxGetI+1)&(FIFOSIZE-1);
|
||
|
|
OS_Signal(&ESP8266TxSpaceAvailable);
|
||
|
|
return SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
//------------ESP8266TxFifo_Size------------
|
||
|
|
// Returns how much data available for reading from Tx1 FIFO
|
||
|
|
// Input: none
|
||
|
|
// Output: number of elements in receive FIFO
|
||
|
|
uint32_t ESP8266TxFifo_Size(void){
|
||
|
|
return ((ESP8266TxPutI - ESP8266TxGetI)&(FIFOSIZE-1));
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
int32_t static ESP8266RxPutI; // Index to put new
|
||
|
|
int32_t static ESP8266RxGetI; // Index of oldest
|
||
|
|
char static ESP8266RxFifo[FIFOSIZE];
|
||
|
|
Sema4_t ESP8266RxDataAvailable; // Lab 6: counting semaphore for available data
|
||
|
|
|
||
|
|
// *********** ESP8266RxFifo_Init**********
|
||
|
|
// Initializes a software RxFIFO of a
|
||
|
|
// fixed size and sets up indexes for
|
||
|
|
// put and get operations
|
||
|
|
// Lab 6 change: Also initializes RxDataAvailable semaphore to 0
|
||
|
|
void ESP8266RxFifo_Init(void){
|
||
|
|
ESP8266RxPutI = ESP8266RxGetI = 0;
|
||
|
|
OS_InitSemaphore(&ESP8266RxDataAvailable, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
// *********** ESP8266RxFifo_Put**********
|
||
|
|
// Adds an element to the ESP8266RxFIFO
|
||
|
|
// Input: data is character to be inserted
|
||
|
|
// Output: 1 for success, data properly saved
|
||
|
|
// 0 for failure, RxFIFO is full
|
||
|
|
// Lab 6 change: Calls OS_Signal after adding element to wake blocked Get callers (called by ISR)
|
||
|
|
uint32_t ESP8266RxFifo_Put(char data){
|
||
|
|
if(((ESP8266RxPutI+1)&(FIFOSIZE-1)) == ESP8266RxGetI){
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
ESP8266RxFifo[ESP8266RxPutI] = data;
|
||
|
|
ESP8266RxPutI = (ESP8266RxPutI+1)&(FIFOSIZE-1);
|
||
|
|
OS_Signal(&ESP8266RxDataAvailable);
|
||
|
|
return SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
// *********** ESP8266RxFifo_Get**********
|
||
|
|
// Gets an element from the ESP8266RxFIFO
|
||
|
|
// Input: pointer to empty 8-bit variable
|
||
|
|
// Output: If the ESP8266RxFIFO is empty return 0
|
||
|
|
// If the ESP8266RxFIFO has data, remove it, and put in *datapt, return 1
|
||
|
|
// Lab 6 change: Now blocks via OS_Wait if FIFO is empty (called by foreground thread)
|
||
|
|
uint32_t ESP8266RxFifo_Get(char *datapt){
|
||
|
|
OS_Wait(&ESP8266RxDataAvailable);
|
||
|
|
*datapt = ESP8266RxFifo[ESP8266RxGetI];
|
||
|
|
ESP8266RxGetI = (ESP8266RxGetI+1)&(FIFOSIZE-1);
|
||
|
|
return SUCCESS;
|
||
|
|
}
|
||
|
|
//------------ESP8266RxFifo_Size------------
|
||
|
|
// Returns how much data available for reading from Rx FIFO
|
||
|
|
// Input: none
|
||
|
|
// Output: number of elements in receive FIFO
|
||
|
|
uint32_t ESP8266RxFifo_Size(void){
|
||
|
|
return ((ESP8266RxPutI - ESP8266RxGetI)&(FIFOSIZE-1));
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
int32_t static ESP8266Rx0PutI; // Index to put new
|
||
|
|
int32_t static ESP8266Rx0GetI; // Index of oldest
|
||
|
|
char static ESP8266Rx0Fifo[FIFOSIZE];
|
||
|
|
Sema4_t ESP8266Rx0DataAvailable; // Lab 6: counting semaphore for available data
|
||
|
|
|
||
|
|
// *********** ESP8266Rx0Fifo_Init**********
|
||
|
|
// Initializes a software RxFIFO of a
|
||
|
|
// fixed size and sets up indexes for
|
||
|
|
// put and get operations
|
||
|
|
// Lab 6 change: Also initializes Rx0DataAvailable semaphore to 0
|
||
|
|
void ESP8266Rx0Fifo_Init(void){
|
||
|
|
ESP8266Rx0PutI = ESP8266Rx0GetI = 0;
|
||
|
|
OS_InitSemaphore(&ESP8266Rx0DataAvailable, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
// *********** ESP8266Rx0Fifo_Put**********
|
||
|
|
// Adds an element to the ESP8266Rx0FIFO
|
||
|
|
// Input: data is character to be inserted
|
||
|
|
// Output: 1 for success, data properly saved
|
||
|
|
// 0 for failure, RxFIFO is full
|
||
|
|
// Lab 6 change: Calls OS_Signal after adding element to wake blocked Get callers (called by ISR)
|
||
|
|
uint32_t ESP8266Rx0Fifo_Put(char data){
|
||
|
|
if(((ESP8266Rx0PutI+1)&(FIFOSIZE-1)) == ESP8266Rx0GetI){
|
||
|
|
return FAILURE;
|
||
|
|
}
|
||
|
|
ESP8266Rx0Fifo[ESP8266Rx0PutI] = data;
|
||
|
|
ESP8266Rx0PutI = (ESP8266Rx0PutI+1)&(FIFOSIZE-1);
|
||
|
|
OS_Signal(&ESP8266Rx0DataAvailable);
|
||
|
|
return SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
// *********** ESP8266Rx0Fifo_Get**********
|
||
|
|
// Gets an element from the ESP8266Rx0FIFO
|
||
|
|
// Input: pointer to empty 8-bit variable
|
||
|
|
// Output: If the ESP8266Rx0FIFO is empty return 0
|
||
|
|
// If the ESP8266Rx0FIFO has data, remove it, and put in *datapt, return 1
|
||
|
|
// Lab 6 change: Now blocks via OS_Wait if FIFO is empty (called by foreground thread)
|
||
|
|
uint32_t ESP8266Rx0Fifo_Get(char *datapt){
|
||
|
|
OS_Wait(&ESP8266Rx0DataAvailable);
|
||
|
|
*datapt = ESP8266Rx0Fifo[ESP8266Rx0GetI];
|
||
|
|
ESP8266Rx0GetI = (ESP8266Rx0GetI+1)&(FIFOSIZE-1);
|
||
|
|
return SUCCESS;
|
||
|
|
}
|
||
|
|
//------------ESP8266Rx0Fifo_Size------------
|
||
|
|
// Returns how much data available for reading from Rx0 FIFO
|
||
|
|
// Input: none
|
||
|
|
// Output: number of elements in receive FIFO
|
||
|
|
uint32_t ESP8266Rx0Fifo_Size(void){
|
||
|
|
return ((ESP8266Rx0PutI - ESP8266Rx0GetI)&(FIFOSIZE-1));
|
||
|
|
}
|
||
|
|
|
||
|
|
|