├── Makefile ├── README.md ├── driver ├── mcp23s17.c └── spi.c ├── firmware ├── 0x00000.bin └── 0x40000.bin ├── include ├── driver │ ├── mcp23s17.h │ ├── mcp23s17_register.h │ ├── spi.h │ └── spi_register.h └── user_config.h └── user └── user_main.c /Makefile: -------------------------------------------------------------------------------- 1 | # tnx to mamalala 2 | # Changelog 3 | # Changed the variables to include the header file directory 4 | # Added global var for the XTENSA tool root 5 | # 6 | # This make file still needs some work. 7 | # 8 | # 9 | # Output directors to store intermediate compiled files 10 | # relative to the project directory 11 | BUILD_BASE = build 12 | #FW_BASE = ../../Build 13 | FW_BASE = firmware 14 | 15 | # Base directory for the compiler 16 | XTENSA_TOOLS_ROOT ?= /opt/esp-open-sdk/xtensa-lx106-elf/bin 17 | 18 | # base directory of the ESP8266 SDK package, absolute 19 | SDK_BASE ?= /opt/esp-open-sdk/sdk 20 | 21 | #Esptool.py path and port 22 | ESPTOOL ?= esptool.py 23 | ESPPORT ?= /dev/ttyUSB0 24 | 25 | # name for the target project 26 | TARGET = app 27 | 28 | # which modules (subdirectories) of the project to include in compiling 29 | MODULES = driver user 30 | EXTRA_INCDIR = include /opt/esp-open-sdk/include 31 | 32 | # libraries used in this project, mainly provided by the SDK 33 | LIBS = c gcc hal pp phy net80211 lwip wpa main ssl smartconfig 34 | 35 | # compiler flags using during compilation of source files 36 | CFLAGS = -Os -g -O2 -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH 37 | 38 | # linker flags used to generate the main object file 39 | LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static 40 | 41 | # linker script used for the above linkier step 42 | LD_SCRIPT = eagle.app.v6.ld 43 | 44 | # various paths from the SDK used in this project 45 | SDK_LIBDIR = lib 46 | SDK_LDDIR = ld 47 | SDK_INCDIR = include include/json 48 | 49 | # we create two different files for uploading into the flash 50 | # these are the names and options to generate them 51 | FW_FILE_1 = 0x00000 52 | FW_FILE_1_ARGS = -bo $@ -bs .text -bs .data -bs .rodata -bc -ec 53 | FW_FILE_2 = 0x40000 54 | FW_FILE_2_ARGS = -es .irom0.text $@ -ec 55 | 56 | # select which tools to use as compiler, librarian and linker 57 | CC := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 58 | AR := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-ar 59 | LD := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc 60 | 61 | 62 | 63 | #### 64 | #### no user configurable options below here 65 | #### 66 | FW_TOOL ?= /usr/bin/esptool 67 | SRC_DIR := $(MODULES) 68 | BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES)) 69 | 70 | SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR)) 71 | SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR)) 72 | 73 | SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) 74 | OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) 75 | LIBS := $(addprefix -l,$(LIBS)) 76 | APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a) 77 | TARGET_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).out) 78 | 79 | LD_SCRIPT := $(addprefix -T$(SDK_BASE)/$(SDK_LDDIR)/,$(LD_SCRIPT)) 80 | 81 | INCDIR := $(addprefix -I,$(SRC_DIR)) 82 | EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR)) 83 | MODULE_INCDIR := $(addsuffix /include,$(INCDIR)) 84 | 85 | FW_FILE_1 := $(addprefix $(FW_BASE)/,$(FW_FILE_1).bin) 86 | FW_FILE_2 := $(addprefix $(FW_BASE)/,$(FW_FILE_2).bin) 87 | 88 | V ?= $(VERBOSE) 89 | ifeq ("$(V)","1") 90 | Q := 91 | vecho := @true 92 | else 93 | Q := @ 94 | vecho := @echo 95 | endif 96 | 97 | vpath %.c $(SRC_DIR) 98 | 99 | define compile-objects 100 | $1/%.o: %.c 101 | $(vecho) "CC $$<" 102 | $(Q) $(CC) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@ 103 | endef 104 | 105 | .PHONY: all checkdirs flash clean 106 | 107 | all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2) 108 | 109 | $(FW_FILE_1): $(TARGET_OUT) 110 | $(vecho) "FW $@" 111 | $(Q) $(FW_TOOL) -eo $(TARGET_OUT) $(FW_FILE_1_ARGS) 112 | 113 | $(FW_FILE_2): $(TARGET_OUT) 114 | $(vecho) "FW $@" 115 | $(Q) $(FW_TOOL) -eo $(TARGET_OUT) $(FW_FILE_2_ARGS) 116 | 117 | $(TARGET_OUT): $(APP_AR) 118 | $(vecho) "LD $@" 119 | $(Q) $(LD) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ 120 | 121 | $(APP_AR): $(OBJ) 122 | $(vecho) "AR $@" 123 | $(Q) $(AR) cru $@ $^ 124 | 125 | checkdirs: $(BUILD_DIR) $(FW_BASE) 126 | 127 | $(BUILD_DIR): 128 | $(Q) mkdir -p $@ 129 | 130 | firmware: 131 | $(Q) mkdir -p $@ 132 | 133 | flash: firmware/0x00000.bin firmware/0x40000.bin 134 | -$(ESPTOOL) --port $(ESPPORT) write_flash 0x00000 firmware/0x00000.bin 0x40000 firmware/0x40000.bin 135 | 136 | clean: 137 | $(Q) rm -f $(APP_AR) 138 | $(Q) rm -f $(TARGET_OUT) 139 | $(Q) rm -rf $(BUILD_DIR) 140 | $(Q) rm -rf $(BUILD_BASE) 141 | 142 | 143 | $(Q) rm -f $(FW_FILE_1) 144 | $(Q) rm -f $(FW_FILE_2) 145 | $(Q) rm -rf $(FW_BASE) 146 | 147 | $(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir)))) 148 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ESP8266 GPIO16 TCP Example Project 2 | ======== 3 | 4 | Example project for controlling 16 GPIO pins (via Microchip MCP23S17 SPI Expansion Chip) over Wifi using TCP packets. 5 | 6 | Connect your ESP8266 Pins up to the MCP23S17 according to the below table 7 | 8 | | ESP GPIO # | SPI Function | MCP23S17 | 9 | |------------|---------------|-------------| 10 | | GPIO12 | MISO (DIN) | Pin 14 (SO) | 11 | | GPIO13 | MOSI (DOUT) | Pin 13 (SI) | 12 | | GPIO14 | CLOCK | Pin 12 (SCK)| 13 | | GPIO15 | CS / SS | Pin 11 (CS) | 14 | 15 | Connect A0, A1, and A2 pins on the MCP23S17 to ground (Pins 15/16/17) 16 | Connect RESET on the MCP23S17 to VCC (+3.3V) using a 1k/4.7k/10k pullup resistor 17 | Leave INTA and INTB unconnected on the MCP23S17 18 | 19 | You can define the SSID and SSID_PASSWORD for your wireless AP to connect the ESP8266 to your local network at the top of the user_main.c file. 20 | 21 | You can define the starting text of the SoftAP_SSID also. The remainder of the SSID will be the ESP8266 SoftAP MAC address. 22 | The SoftAP_SSID_PASSWORD can also be set along with the encryption mode (AP_AUTH). 23 | 24 | The SoftAP uses IP 192.168.5.1 for the ESP8266, and gives out DHCP addresses for connecting devices from 192.168.5.2 to 192.168.5.100 25 | 26 | TCP Listener 27 | ======== 28 | The ESP8266 listens on port 33333 for a TCP packet. The packet format is a simple 2 Byte packet. 29 | 30 | Send "0xFF 0xFF" to turn on all outputs. 31 | 32 | Structure of the 16bit packet is: 33 | 34 | A7|A6|A5|A4|A3|A2|A1|A0|B7|B6|B5|B4|B3|B2|B1|B0 35 | 36 | Which correspont to the GPIO pins on the MCP23S17. 37 | 38 | Using netcat you can do the following command to send a packet: 39 | 40 | echo -ne '\x00\xFF' | nc 192.168.5.1 33333 41 | 42 | Makefile 43 | ======== 44 | The makefile is setup for using the esp-open-sdk installed in /opt/esp-open-sdk 45 | 46 | Modify the makefile to match your install setup or use your own Makefile from a working project. -------------------------------------------------------------------------------- /driver/mcp23s17.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015 David Ogilvy (MetalPhreak) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | 26 | #include "driver/mcp23s17.h" 27 | 28 | #define SPI_DEV HSPI 29 | 30 | //////////////////////////////////////////////////////////////////////////////// 31 | // 32 | // Function Name: mcp23s17_init 33 | // Description: Initialises SPI hardware for 10MHz operation & configures 34 | // all attached MCP23S17 devices for individual addressing. 35 | // Parameters: none 36 | // 37 | //////////////////////////////////////////////////////////////////////////////// 38 | 39 | void mcp23s17_init(){ 40 | //init SPI bus 41 | spi_init_gpio(SPI_DEV, SPI_CLK_USE_DIV); 42 | spi_clock(SPI_DEV, 4, 2); //10MHz 43 | spi_tx_byte_order(SPI_DEV, SPI_BYTE_ORDER_HIGH_TO_LOW); 44 | spi_rx_byte_order(SPI_DEV, SPI_BYTE_ORDER_HIGH_TO_LOW); 45 | 46 | SET_PERI_REG_MASK(SPI_USER(SPI_DEV), SPI_CS_SETUP|SPI_CS_HOLD); 47 | CLEAR_PERI_REG_MASK(SPI_USER(SPI_DEV), SPI_FLASH_MODE); 48 | 49 | //Enable hardware addressing & sequential addressing on all devices 50 | mcp23s17_REG_SET(IOCON_CTRL, PORTA, SEQOP|HAEN); 51 | 52 | } 53 | 54 | //////////////////////////////////////////////////////////////////////////////// 55 | 56 | //////////////////////////////////////////////////////////////////////////////// 57 | // 58 | // Function Name: mcp23s17_REG_SET 59 | // Description: Set register value 60 | // Parameters: ctrl_reg - control register to set 61 | // port - port to control 62 | // value - value to set 63 | // 64 | //////////////////////////////////////////////////////////////////////////////// 65 | 66 | void mcp23s17_REG_SET(uint8 ctrl_reg, uint8 port, uint16 value){ 67 | 68 | uint8 cmd = (0x20|(port>>2))<<1; //0b0100[Address][WRITE] 69 | 70 | if (port & 0x02){ 71 | spi_transaction(SPI_DEV, 8, cmd, 8, ctrl_reg, 16, value, 0, 0); 72 | } else { 73 | spi_transaction(SPI_DEV, 8, cmd, 8, ctrl_reg+(port&0x01), 8, value, 0, 0); 74 | } 75 | } 76 | 77 | //////////////////////////////////////////////////////////////////////////////// 78 | 79 | //////////////////////////////////////////////////////////////////////////////// 80 | // 81 | // Function Name: mcp23s17_REG_GET 82 | // Description: Get register value 83 | // Parameters: ctrl_reg - control register to get 84 | // port - port to control 85 | // 86 | //////////////////////////////////////////////////////////////////////////////// 87 | 88 | uint16 mcp23s17_REG_GET(uint8 ctrl_reg, uint8 port){ 89 | 90 | uint8 cmd = ((0x20|(port>>2))<<1)|0x01; //0b0100[Address][READ] 91 | 92 | if (port & 0x02){ 93 | return spi_transaction(SPI_DEV, 8, cmd, 8, ctrl_reg, 0, 0, 16, 0); 94 | } else { 95 | return (uint16) spi_transaction(SPI_DEV, 8, cmd, 8, ctrl_reg+(port&0x01), 0, 0, 8, 0); 96 | } 97 | } 98 | 99 | //////////////////////////////////////////////////////////////////////////////// 100 | 101 | //////////////////////////////////////////////////////////////////////////////// 102 | // 103 | // Function Name: mcp23s17_REG_SET_MASK 104 | // Description: Set register value bits with a mask 105 | // Parameters: ctrl_reg - control register to set 106 | // port - port to control 107 | // value - value to set 108 | // bitmask - which bits to change 109 | // 110 | //////////////////////////////////////////////////////////////////////////////// 111 | 112 | void mcp23s17_REG_SET_MASK(uint8 ctrl_reg, uint8 port, uint16 value, uint16 bitmask){ 113 | 114 | uint16 current_value = ~bitmask & mcp23s17_REG_GET(ctrl_reg, port); 115 | uint16 set_value = bitmask & value; 116 | 117 | mcp23s17_REG_SET(ctrl_reg, port, current_value|set_value); 118 | 119 | } 120 | 121 | //////////////////////////////////////////////////////////////////////////////// 122 | 123 | /*/////////////////////////////////////////////////////////////////////////////// 124 | // 125 | // Function Name: func 126 | // Description: 127 | // Parameters: 128 | // 129 | //////////////////////////////////////////////////////////////////////////////// 130 | 131 | void func(params){ 132 | 133 | } 134 | 135 | ///////////////////////////////////////////////////////////////////////////////*/ 136 | 137 | 138 | -------------------------------------------------------------------------------- /driver/spi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015 David Ogilvy (MetalPhreak) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | 26 | #include "driver/spi.h" 27 | 28 | 29 | //////////////////////////////////////////////////////////////////////////////// 30 | // 31 | // Function Name: spi_init 32 | // Description: Wrapper to setup HSPI/SPI GPIO pins and default SPI clock 33 | // Parameters: spi_no - SPI (0) or HSPI (1) 34 | // 35 | //////////////////////////////////////////////////////////////////////////////// 36 | 37 | void spi_init(uint8 spi_no){ 38 | 39 | if(spi_no > 1) return; //Only SPI and HSPI are valid spi modules. 40 | 41 | spi_init_gpio(spi_no, SPI_CLK_USE_DIV); 42 | spi_clock(spi_no, SPI_CLK_PREDIV, SPI_CLK_CNTDIV); 43 | spi_tx_byte_order(spi_no, SPI_BYTE_ORDER_HIGH_TO_LOW); 44 | spi_rx_byte_order(spi_no, SPI_BYTE_ORDER_HIGH_TO_LOW); 45 | 46 | SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_CS_SETUP|SPI_CS_HOLD); 47 | CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_FLASH_MODE); 48 | 49 | } 50 | 51 | //////////////////////////////////////////////////////////////////////////////// 52 | 53 | //////////////////////////////////////////////////////////////////////////////// 54 | // 55 | // Function Name: spi_init_gpio 56 | // Description: Initialises the GPIO pins for use as SPI pins. 57 | // Parameters: spi_no - SPI (0) or HSPI (1) 58 | // sysclk_as_spiclk - SPI_CLK_80MHZ_NODIV (1) if using 80MHz 59 | // sysclock for SPI clock. 60 | // SPI_CLK_USE_DIV (0) if using divider to 61 | // get lower SPI clock speed. 62 | // 63 | //////////////////////////////////////////////////////////////////////////////// 64 | 65 | void spi_init_gpio(uint8 spi_no, uint8 sysclk_as_spiclk){ 66 | 67 | // if(spi_no > 1) return; //Not required. Valid spi_no is checked with if/elif below. 68 | 69 | uint32 clock_div_flag = 0; 70 | if(sysclk_as_spiclk){ 71 | clock_div_flag = 0x0001; 72 | } 73 | 74 | if(spi_no==SPI){ 75 | WRITE_PERI_REG(PERIPHS_IO_MUX, 0x005|(clock_div_flag<<8)); //Set bit 8 if 80MHz sysclock required 76 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, 1); 77 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 1); 78 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, 1); 79 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, 1); 80 | }else if(spi_no==HSPI){ 81 | WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105|(clock_div_flag<<9)); //Set bit 9 if 80MHz sysclock required 82 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2); //GPIO12 is HSPI MISO pin (Master Data In) 83 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2); //GPIO13 is HSPI MOSI pin (Master Data Out) 84 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2); //GPIO14 is HSPI CLK pin (Clock) 85 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2); //GPIO15 is HSPI CS pin (Chip Select / Slave Select) 86 | } 87 | 88 | } 89 | 90 | //////////////////////////////////////////////////////////////////////////////// 91 | 92 | //////////////////////////////////////////////////////////////////////////////// 93 | // 94 | // Function Name: spi_clock 95 | // Description: sets up the control registers for the SPI clock 96 | // Parameters: spi_no - SPI (0) or HSPI (1) 97 | // prediv - predivider value (actual division value) 98 | // cntdiv - postdivider value (actual division value) 99 | // Set either divider to 0 to disable all division (80MHz sysclock) 100 | // 101 | //////////////////////////////////////////////////////////////////////////////// 102 | 103 | void spi_clock(uint8 spi_no, uint16 prediv, uint8 cntdiv){ 104 | 105 | if(spi_no > 1) return; 106 | 107 | if((prediv==0)|(cntdiv==0)){ 108 | 109 | WRITE_PERI_REG(SPI_CLOCK(spi_no), SPI_CLK_EQU_SYSCLK); 110 | 111 | } else { 112 | 113 | WRITE_PERI_REG(SPI_CLOCK(spi_no), 114 | (((prediv-1)&SPI_CLKDIV_PRE)<>1)&SPI_CLKCNT_H)< 1) return; 145 | 146 | if(byte_order){ 147 | SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_WR_BYTE_ORDER); 148 | } else { 149 | CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_WR_BYTE_ORDER); 150 | } 151 | } 152 | //////////////////////////////////////////////////////////////////////////////// 153 | 154 | //////////////////////////////////////////////////////////////////////////////// 155 | // 156 | // Function Name: spi_rx_byte_order 157 | // Description: Setup the byte order for shifting data into buffer 158 | // Parameters: spi_no - SPI (0) or HSPI (1) 159 | // byte_order - SPI_BYTE_ORDER_HIGH_TO_LOW (1) 160 | // Data is read in starting with Bit31 and down to Bit0 161 | // 162 | // SPI_BYTE_ORDER_LOW_TO_HIGH (0) 163 | // Data is read in starting with the lowest BYTE, from 164 | // MSB to LSB, followed by the second lowest BYTE, from 165 | // MSB to LSB, followed by the second highest BYTE, from 166 | // MSB to LSB, followed by the highest BYTE, from MSB to LSB 167 | // 0xABCDEFGH would be read as 0xGHEFCDAB 168 | // 169 | // 170 | //////////////////////////////////////////////////////////////////////////////// 171 | 172 | void spi_rx_byte_order(uint8 spi_no, uint8 byte_order){ 173 | 174 | if(spi_no > 1) return; 175 | 176 | if(byte_order){ 177 | SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_RD_BYTE_ORDER); 178 | } else { 179 | CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_RD_BYTE_ORDER); 180 | } 181 | } 182 | //////////////////////////////////////////////////////////////////////////////// 183 | 184 | //////////////////////////////////////////////////////////////////////////////// 185 | // 186 | // Function Name: spi_transaction 187 | // Description: SPI transaction function 188 | // Parameters: spi_no - SPI (0) or HSPI (1) 189 | // cmd_bits - actual number of bits to transmit 190 | // cmd_data - command data 191 | // addr_bits - actual number of bits to transmit 192 | // addr_data - address data 193 | // dout_bits - actual number of bits to transmit 194 | // dout_data - output data 195 | // din_bits - actual number of bits to receive 196 | // 197 | // Returns: read data - uint32 containing read in data only if RX was set 198 | // 0 - something went wrong (or actual read data was 0) 199 | // 1 - data sent ok (or actual read data is 1) 200 | // Note: all data is assumed to be stored in the lower bits of 201 | // the data variables (for anything <32 bits). 202 | // 203 | //////////////////////////////////////////////////////////////////////////////// 204 | 205 | uint32 spi_transaction(uint8 spi_no, uint8 cmd_bits, uint16 cmd_data, uint32 addr_bits, uint32 addr_data, uint32 dout_bits, uint32 dout_data, 206 | uint32 din_bits, uint32 dummy_bits){ 207 | 208 | if(spi_no > 1) return 0; //Check for a valid SPI 209 | 210 | //code for custom Chip Select as GPIO PIN here 211 | 212 | while(spi_busy()); //wait for SPI to be ready 213 | 214 | //########## Enable SPI Functions ##########// 215 | //disable MOSI, MISO, ADDR, COMMAND, DUMMY in case previously set. 216 | CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI|SPI_USR_MISO|SPI_USR_COMMAND|SPI_USR_ADDR|SPI_USR_DUMMY); 217 | 218 | //enable functions based on number of bits. 0 bits = disabled. 219 | //This is rather inefficient but allows for a very generic function. 220 | //CMD ADDR and MOSI are set below to save on an extra if statement. 221 | // if(cmd_bits) {SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_COMMAND);} 222 | // if(addr_bits) {SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_ADDR);} 223 | if(din_bits) {SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MISO);} 224 | if(dummy_bits) {SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_DUMMY);} 225 | //########## END SECTION ##########// 226 | 227 | //########## Setup Bitlengths ##########// 228 | WRITE_PERI_REG(SPI_USER1(spi_no), ((addr_bits-1)&SPI_USR_ADDR_BITLEN)<>8)&0xff) | ((command<<8)&0xff00); //swap byte order 239 | WRITE_PERI_REG(SPI_USER2(spi_no), ((((cmd_bits-1)&SPI_USR_COMMAND_BITLEN)<>(32-(dout_bits - dout_extra_bits)))&dout_data)); 269 | } else { 270 | WRITE_PERI_REG(SPI_W0(spi_no), dout_data); 271 | } 272 | } 273 | } 274 | //########## END SECTION ##########// 275 | 276 | //########## Begin SPI Transaction ##########// 277 | SET_PERI_REG_MASK(SPI_CMD(spi_no), SPI_USR); 278 | //########## END SECTION ##########// 279 | 280 | //########## Return DIN data ##########// 281 | if(din_bits) { 282 | while(READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR); //wait for SPI transaction to complete 283 | 284 | if(READ_PERI_REG(SPI_USER(spi_no))&SPI_RD_BYTE_ORDER) { 285 | return READ_PERI_REG(SPI_W0(spi_no)) >> (32-din_bits); //Assuming data in is written to MSB. TBC 286 | } else { 287 | return READ_PERI_REG(SPI_W0(spi_no)); //Read in the same way as DOUT is sent. Note existing contents of SPI_W0 remain unless overwritten! 288 | } 289 | 290 | return 0; //something went wrong 291 | } 292 | //########## END SECTION ##########// 293 | 294 | //Transaction completed 295 | return 1; //success 296 | } 297 | 298 | //////////////////////////////////////////////////////////////////////////////// 299 | 300 | /*/////////////////////////////////////////////////////////////////////////////// 301 | // 302 | // Function Name: func 303 | // Description: 304 | // Parameters: 305 | // 306 | //////////////////////////////////////////////////////////////////////////////// 307 | 308 | void func(params){ 309 | 310 | } 311 | 312 | ///////////////////////////////////////////////////////////////////////////////*/ 313 | 314 | 315 | -------------------------------------------------------------------------------- /firmware/0x00000.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetalPhreak/ESP8266_GPIO16_TCP_Example/459421d7f2ca3e2606073be2cc2749dfdf66c90b/firmware/0x00000.bin -------------------------------------------------------------------------------- /firmware/0x40000.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetalPhreak/ESP8266_GPIO16_TCP_Example/459421d7f2ca3e2606073be2cc2749dfdf66c90b/firmware/0x40000.bin -------------------------------------------------------------------------------- /include/driver/mcp23s17.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015 David Ogilvy (MetalPhreak) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #ifndef MCP23S17_H 26 | #define MCP23S17_H 27 | 28 | #include "driver/spi.h" 29 | #include "driver/mcp23s17_register.h" 30 | 31 | 32 | void mcp23s17_init(); 33 | void mcp23s17_REG_SET(uint8 ctrl_reg, uint8 port, uint16 value); 34 | uint16 mcp23s17_REG_GET(uint8 ctrl_reg, uint8 port); 35 | void mcp23s17_REG_SET_MASK(uint8 ctrl_reg, uint8 port, uint16 value, uint16 bitmask); 36 | 37 | #define sGPIO_SET(port, value) mcp23s17_REG_SET(OLAT_CTRL, port, value) 38 | #define sGPIO_SET_MASK(port, value, bitmask) mcp23s17_REG_SET_MASK(OLAT_CTRL, port, value, bitmask) 39 | #define sGPIO_SET_PIN(port, pin, value) mcp23s17_REG_SET_MASK(OLAT_CTRL, port, value<<(pin-1), 1<<(pin-1)) 40 | 41 | #define sGPIO_GET(port) mcp23s17_REG_GET(OLAT_CTRL, port) 42 | 43 | #define sGPIO_READ(port) mcp23s17_REG_GET(GPIO_CTRL, port) 44 | 45 | 46 | 47 | 48 | 49 | 50 | #endif 51 | 52 | -------------------------------------------------------------------------------- /include/driver/mcp23s17_register.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015 David Ogilvy (MetalPhreak) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #ifndef MCP23S17_REGISTER_H 26 | #define MCP23S17_REGISTER_H 27 | 28 | // 0b000ADDMP 29 | // | |^^ Port: 0 = PORTA#; 1 = PORTB#; x = Don't Care for 16bit I/O Setup 30 | // ^ ^ Mode: 0 = 8bit; 1 = 16bit 31 | // ^ Device ADDress: 000 = Chip 0, 001 = Chip 1 ... 111 = Chip 7 32 | 33 | #define PORTA0 0x00 34 | #define PORTB0 0x01 35 | #define PORT0 0x02 36 | 37 | #define PORTA1 0x04 38 | #define PORTB1 0x05 39 | #define PORT1 0x06 40 | 41 | #define PORTA2 0x08 42 | #define PORTB2 0x09 43 | #define PORT2 0x0A 44 | 45 | #define PORTA3 0x0C 46 | #define PORTB3 0x0D 47 | #define PORT3 0x0E 48 | 49 | #define PORTA4 0x10 50 | #define PORTB4 0x11 51 | #define PORT4 0x12 52 | 53 | #define PORTA5 0x14 54 | #define PORTB5 0x15 55 | #define PORT5 0x16 56 | 57 | #define PORTA6 0x18 58 | #define PORTB6 0x19 59 | #define PORT6 0x1A 60 | 61 | #define PORTA7 0x1C 62 | #define PORTB7 0x1D 63 | #define PORT7 0x1E 64 | 65 | //If you only have one device, you can use the below for simplicity. 66 | //Connect all address pins to ground, or change the below defines to match your address setting. 67 | #define PORTA PORTA0 68 | #define PORTB PORTB0 69 | #define PORT PORT0 70 | 71 | #define GPIO0 0x0001 72 | #define GPIO1 0x0002 73 | #define GPIO2 0x0004 74 | #define GPIO3 0x0008 75 | #define GPIO4 0x0010 76 | #define GPIO5 0x0020 77 | #define GPIO6 0x0040 78 | #define GPIO7 0x0080 79 | #define GPIO8 0x0100 80 | #define GPIO9 0x0200 81 | #define GPIO10 0x0400 82 | #define GPIO11 0x0800 83 | #define GPIO12 0x1000 84 | #define GPIO13 0x2000 85 | #define GPIO14 0x4000 86 | #define GPIO15 0x8000 87 | 88 | //IOCON.Bank = 0 by default on startup which is better for using 16bit mode (and just as good for 8bit) 89 | 90 | //These control register maps are valid only when IOCON.Bank = 0! 91 | 92 | //Can use these only with PORTAx/PORTBx respectively 93 | #define IODIRA 0x00 94 | #define IODIRB 0x01 95 | #define IPOLA 0x02 96 | #define IPOLB 0x03 97 | #define GPINTENA 0x04 98 | #define GPINTENB 0x05 99 | #define DEFVALA 0x06 100 | #define DEFVALB 0x07 101 | #define INTCONA 0x08 102 | #define INTCONB 0x09 103 | #define IOCONA 0x0A 104 | #define IOCONB 0x0B 105 | #define GPPUA 0x0C 106 | #define GPPUB 0x0D 107 | #define INTFA 0x0E 108 | #define INTFB 0x0F 109 | #define INTCAPA 0x10 110 | #define INTCAPB 0x11 111 | #define GPIOA 0x12 112 | #define GPIOB 0x13 113 | #define OLATA 0x14 114 | #define OLATB 0x15 115 | 116 | //Can use these names for control registers for all PORTAx/PORTBx/PORTx 117 | #define IODIR_CTRL 0x00 118 | #define IPOL_CTRL 0x02 119 | #define GPINTEN_CTRL 0x04 120 | #define DEFVAL_CTRL 0x06 121 | #define INTCON_CTRL 0x08 122 | #define IOCON_CTRL 0x0A 123 | #define GPPU_CTRL 0x0C 124 | #define INTF_CTRL 0x0E 125 | #define INTCAP_CTRL 0x10 126 | #define GPIO_CTRL 0x12 127 | #define OLAT_CTRL 0x14 128 | 129 | 130 | //IOCON bits 131 | #define INTPOL 0x02 132 | #define ODR 0x04 133 | #define HAEN 0x08 134 | #define DISSLW 0x10 135 | #define SEQOP 0x20 136 | #define MIRROR 0x40 137 | #define BANK 0x80 138 | 139 | #endif 140 | 141 | -------------------------------------------------------------------------------- /include/driver/spi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015 David Ogilvy (MetalPhreak) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #ifndef SPI_APP_H 26 | #define SPI_APP_H 27 | 28 | #include "spi_register.h" 29 | #include "ets_sys.h" 30 | #include "osapi.h" 31 | //#include "uart.h" 32 | #include "os_type.h" 33 | 34 | //Define SPI hardware modules 35 | #define SPI 0 36 | #define HSPI 1 37 | 38 | #define SPI_CLK_USE_DIV 0 39 | #define SPI_CLK_80MHZ_NODIV 1 40 | 41 | #define SPI_BYTE_ORDER_HIGH_TO_LOW 1 42 | #define SPI_BYTE_ORDER_LOW_TO_HIGH 0 43 | 44 | #ifndef CPU_CLK_FREQ //Should already be defined in eagle_soc.h 45 | #define CPU_CLK_FREQ 80*1000000 46 | #endif 47 | 48 | //Define some default SPI clock settings 49 | #define SPI_CLK_PREDIV 10 50 | #define SPI_CLK_CNTDIV 2 51 | #define SPI_CLK_FREQ CPU_CLK_FREQ/(SPI_CLK_PREDIV*SPI_CLK_CNTDIV) // 80 / 20 = 4 MHz 52 | 53 | 54 | 55 | 56 | 57 | void spi_init(uint8 spi_no); 58 | void spi_init_gpio(uint8 spi_no, uint8 sysclk_as_spiclk); 59 | void spi_clock(uint8 spi_no, uint16 prediv, uint8 cntdiv); 60 | void spi_tx_byte_order(uint8 spi_no, uint8 byte_order); 61 | void spi_rx_byte_order(uint8 spi_no, uint8 byte_order); 62 | uint32 spi_transaction(uint8 spi_no, uint8 cmd_bits, uint16 cmd_data, uint32 addr_bits, uint32 addr_data, uint32 dout_bits, uint32 dout_data, uint32 din_bits, uint32 dummy_bits); 63 | 64 | //Expansion Macros 65 | #define spi_busy() READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR 66 | 67 | #define spi_txd(spi_no, bits, data) spi_transaction(spi_no, 0, 0, 0, 0, bits, (uint32) data, 0, 0) 68 | #define spi_tx8(spi_no, data) spi_transaction(spi_no, 0, 0, 0, 0, 8, (uint32) data, 0, 0) 69 | #define spi_tx16(spi_no, data) spi_transaction(spi_no, 0, 0, 0, 0, 16, (uint32) data, 0, 0) 70 | #define spi_tx32(spi_no, data) spi_transaction(spi_no, 0, 0, 0, 0, 32, (uint32) data, 0, 0) 71 | 72 | #define spi_rxd(spi_no, bits) spi_transaction(spi_no, 0, 0, 0, 0, 0, 0, bits, 0) 73 | #define spi_rx8(spi_no) spi_transaction(spi_no, 0, 0, 0, 0, 0, 0, 8, 0) 74 | #define spi_rx16(spi_no) spi_transaction(spi_no, 0, 0, 0, 0, 0, 0, 16, 0) 75 | #define spi_rx32(spi_no) spi_transaction(spi_no, 0, 0, 0, 0, 0, 0, 32, 0) 76 | 77 | #endif 78 | 79 | -------------------------------------------------------------------------------- /include/driver/spi_register.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010 - 2011 Espressif System 3 | * Modified by David Ogilvy (MetalPhreak) 4 | * Based on original file included in SDK 1.0.0 5 | * 6 | * Missing defines from previous SDK versions have 7 | * been added and are noted with comments. The 8 | * names of these defines are likely to change. 9 | */ 10 | 11 | #ifndef SPI_REGISTER_H_INCLUDED 12 | #define SPI_REGISTER_H_INCLUDED 13 | 14 | #define REG_SPI_BASE(i) (0x60000200-i*0x100) 15 | 16 | #define SPI_CMD(i) (REG_SPI_BASE(i) + 0x0) 17 | #define SPI_FLASH_READ (BIT(31)) //From previous SDK 18 | #define SPI_FLASH_WREN (BIT(30)) //From previous SDK 19 | #define SPI_FLASH_WRDI (BIT(29)) //From previous SDK 20 | #define SPI_FLASH_RDID (BIT(28)) //From previous SDK 21 | #define SPI_FLASH_RDSR (BIT(27)) //From previous SDK 22 | #define SPI_FLASH_WRSR (BIT(26)) //From previous SDK 23 | #define SPI_FLASH_PP (BIT(25)) //From previous SDK 24 | #define SPI_FLASH_SE (BIT(24)) //From previous SDK 25 | #define SPI_FLASH_BE (BIT(23)) //From previous SDK 26 | #define SPI_FLASH_CE (BIT(22)) //From previous SDK 27 | #define SPI_FLASH_DP (BIT(21)) //From previous SDK 28 | #define SPI_FLASH_RES (BIT(20)) //From previous SDK 29 | #define SPI_FLASH_HPM (BIT(19)) //From previous SDK 30 | #define SPI_USR (BIT(18)) 31 | 32 | #define SPI_ADDR(i) (REG_SPI_BASE(i) + 0x4) 33 | 34 | #define SPI_CTRL(i) (REG_SPI_BASE(i) + 0x8) 35 | #define SPI_WR_BIT_ORDER (BIT(26)) 36 | #define SPI_RD_BIT_ORDER (BIT(25)) 37 | #define SPI_QIO_MODE (BIT(24)) 38 | #define SPI_DIO_MODE (BIT(23)) 39 | #define SPI_TWO_BYTE_STATUS_EN (BIT(22)) //From previous SDK 40 | #define SPI_WP_REG (BIT(21)) //From previous SDK 41 | #define SPI_QOUT_MODE (BIT(20)) 42 | #define SPI_SHARE_BUS (BIT(19)) //From previous SDK 43 | #define SPI_HOLD_MODE (BIT(18)) //From previous SDK 44 | #define SPI_ENABLE_AHB (BIT(17)) //From previous SDK 45 | #define SPI_SST_AAI (BIT(16)) //From previous SDK 46 | #define SPI_RESANDRES (BIT(15)) //From previous SDK 47 | #define SPI_DOUT_MODE (BIT(14)) 48 | #define SPI_FASTRD_MODE (BIT(13)) 49 | 50 | #define SPI_CTRL1(i) (REG_SPI_BASE (i) + 0xC) //From previous SDK. Removed _FLASH_ from name to match other registers. 51 | #define SPI_T_CSH 0x0000000F //From previous SDK 52 | #define SPI_T_CSH_S 28 //From previous SDK 53 | #define SPI_T_RES 0x00000FFF //From previous SDK 54 | #define SPI_T_RES_S 16 //From previous SDK 55 | #define SPI_BUS_TIMER_LIMIT 0x0000FFFF //From previous SDK 56 | #define SPI_BUS_TIMER_LIMIT_S 0 //From previous SDK 57 | 58 | #define SPI_RD_STATUS(i) (REG_SPI_BASE(i) + 0x10) 59 | #define SPI_STATUS_EXT 0x000000FF //From previous SDK 60 | #define SPI_STATUS_EXT_S 24 //From previous SDK 61 | #define SPI_WB_MODE 0x000000FF //From previous SDK 62 | #define SPI_WB_MODE_S 16 //From previous SDK 63 | #define SPI_FLASH_STATUS_PRO_FLAG (BIT(7)) //From previous SDK 64 | #define SPI_FLASH_TOP_BOT_PRO_FLAG (BIT(5)) //From previous SDK 65 | #define SPI_FLASH_BP2 (BIT(4)) //From previous SDK 66 | #define SPI_FLASH_BP1 (BIT(3)) //From previous SDK 67 | #define SPI_FLASH_BP0 (BIT(2)) //From previous SDK 68 | #define SPI_FLASH_WRENABLE_FLAG (BIT(1)) //From previous SDK 69 | #define SPI_FLASH_BUSY_FLAG (BIT(0)) //From previous SDK 70 | 71 | #define SPI_CTRL2(i) (REG_SPI_BASE(i) + 0x14) 72 | #define SPI_CS_DELAY_NUM 0x0000000F 73 | #define SPI_CS_DELAY_NUM_S 28 74 | #define SPI_CS_DELAY_MODE 0x00000003 75 | #define SPI_CS_DELAY_MODE_S 26 76 | #define SPI_MOSI_DELAY_NUM 0x00000007 77 | #define SPI_MOSI_DELAY_NUM_S 23 78 | #define SPI_MOSI_DELAY_MODE 0x00000003 79 | #define SPI_MOSI_DELAY_MODE_S 21 80 | #define SPI_MISO_DELAY_NUM 0x00000007 81 | #define SPI_MISO_DELAY_NUM_S 18 82 | #define SPI_MISO_DELAY_MODE 0x00000003 83 | #define SPI_MISO_DELAY_MODE_S 16 84 | #define SPI_CK_OUT_HIGH_MODE 0x0000000F 85 | #define SPI_CK_OUT_HIGH_MODE_S 12 86 | #define SPI_CK_OUT_LOW_MODE 0x0000000F 87 | #define SPI_CK_OUT_LOW_MODE_S 8 88 | #define SPI_HOLD_TIME 0x0000000F 89 | #define SPI_HOLD_TIME_S 4 90 | #define SPI_SETUP_TIME 0x0000000F 91 | #define SPI_SETUP_TIME_S 0 92 | 93 | #define SPI_CLOCK(i) (REG_SPI_BASE(i) + 0x18) 94 | #define SPI_CLK_EQU_SYSCLK (BIT(31)) 95 | #define SPI_CLKDIV_PRE 0x00001FFF 96 | #define SPI_CLKDIV_PRE_S 18 97 | #define SPI_CLKCNT_N 0x0000003F 98 | #define SPI_CLKCNT_N_S 12 99 | #define SPI_CLKCNT_H 0x0000003F 100 | #define SPI_CLKCNT_H_S 6 101 | #define SPI_CLKCNT_L 0x0000003F 102 | #define SPI_CLKCNT_L_S 0 103 | 104 | #define SPI_USER(i) (REG_SPI_BASE(i) + 0x1C) 105 | #define SPI_USR_COMMAND (BIT(31)) 106 | #define SPI_USR_ADDR (BIT(30)) 107 | #define SPI_USR_DUMMY (BIT(29)) 108 | #define SPI_USR_MISO (BIT(28)) 109 | #define SPI_USR_MOSI (BIT(27)) 110 | #define SPI_USR_DUMMY_IDLE (BIT(26)) //From previous SDK 111 | #define SPI_USR_MOSI_HIGHPART (BIT(25)) 112 | #define SPI_USR_MISO_HIGHPART (BIT(24)) 113 | #define SPI_USR_PREP_HOLD (BIT(23)) //From previous SDK 114 | #define SPI_USR_CMD_HOLD (BIT(22)) //From previous SDK 115 | #define SPI_USR_ADDR_HOLD (BIT(21)) //From previous SDK 116 | #define SPI_USR_DUMMY_HOLD (BIT(20)) //From previous SDK 117 | #define SPI_USR_DIN_HOLD (BIT(19)) //From previous SDK 118 | #define SPI_USR_DOUT_HOLD (BIT(18)) //From previous SDK 119 | #define SPI_USR_HOLD_POL (BIT(17)) //From previous SDK 120 | #define SPI_SIO (BIT(16)) 121 | #define SPI_FWRITE_QIO (BIT(15)) 122 | #define SPI_FWRITE_DIO (BIT(14)) 123 | #define SPI_FWRITE_QUAD (BIT(13)) 124 | #define SPI_FWRITE_DUAL (BIT(12)) 125 | #define SPI_WR_BYTE_ORDER (BIT(11)) 126 | #define SPI_RD_BYTE_ORDER (BIT(10)) 127 | #define SPI_AHB_ENDIAN_MODE 0x00000003 //From previous SDK 128 | #define SPI_AHB_ENDIAN_MODE_S 8 //From previous SDK 129 | #define SPI_CK_OUT_EDGE (BIT(7)) 130 | #define SPI_CK_I_EDGE (BIT(6)) 131 | #define SPI_CS_SETUP (BIT(5)) 132 | #define SPI_CS_HOLD (BIT(4)) 133 | #define SPI_AHB_USR_COMMAND (BIT(3)) //From previous SDK 134 | #define SPI_FLASH_MODE (BIT(2)) 135 | #define SPI_AHB_USR_COMMAND_4BYTE (BIT(1)) //From previous SDK 136 | #define SPI_DOUTDIN (BIT(0)) //From previous SDK 137 | 138 | //AHB = http://en.wikipedia.org/wiki/Advanced_Microcontroller_Bus_Architecture ? 139 | 140 | 141 | #define SPI_USER1(i) (REG_SPI_BASE(i) + 0x20) 142 | #define SPI_USR_ADDR_BITLEN 0x0000003F 143 | #define SPI_USR_ADDR_BITLEN_S 26 144 | #define SPI_USR_MOSI_BITLEN 0x000001FF 145 | #define SPI_USR_MOSI_BITLEN_S 17 146 | #define SPI_USR_MISO_BITLEN 0x000001FF 147 | #define SPI_USR_MISO_BITLEN_S 8 148 | #define SPI_USR_DUMMY_CYCLELEN 0x000000FF 149 | #define SPI_USR_DUMMY_CYCLELEN_S 0 150 | 151 | #define SPI_USER2(i) (REG_SPI_BASE(i) + 0x24) 152 | #define SPI_USR_COMMAND_BITLEN 0x0000000F 153 | #define SPI_USR_COMMAND_BITLEN_S 28 154 | #define SPI_USR_COMMAND_VALUE 0x0000FFFF 155 | #define SPI_USR_COMMAND_VALUE_S 0 156 | 157 | #define SPI_WR_STATUS(i) (REG_SPI_BASE(i) + 0x28) 158 | //previously defined as SPI_FLASH_USER3. No further info available. 159 | 160 | #define SPI_PIN(i) (REG_SPI_BASE(i) + 0x2C) 161 | #define SPI_CS2_DIS (BIT(2)) 162 | #define SPI_CS1_DIS (BIT(1)) 163 | #define SPI_CS0_DIS (BIT(0)) 164 | 165 | #define SPI_SLAVE(i) (REG_SPI_BASE(i) + 0x30) 166 | #define SPI_SYNC_RESET (BIT(31)) 167 | #define SPI_SLAVE_MODE (BIT(30)) 168 | #define SPI_SLV_WR_RD_BUF_EN (BIT(29)) 169 | #define SPI_SLV_WR_RD_STA_EN (BIT(28)) 170 | #define SPI_SLV_CMD_DEFINE (BIT(27)) 171 | #define SPI_TRANS_CNT 0x0000000F 172 | #define SPI_TRANS_CNT_S 23 173 | #define SPI_SLV_LAST_STATE 0x00000007 //From previous SDK 174 | #define SPI_SLV_LAST_STATE_S 20 //From previous SDK 175 | #define SPI_SLV_LAST_COMMAND 0x00000007 //From previous SDK 176 | #define SPI_SLV_LAST_COMMAND_S 17 //From previous SDK 177 | #define SPI_CS_I_MODE 0x00000003 //From previous SDK 178 | #define SPI_CS_I_MODE_S 10 //From previous SDK 179 | #define SPI_TRANS_DONE_EN (BIT(9)) 180 | #define SPI_SLV_WR_STA_DONE_EN (BIT(8)) 181 | #define SPI_SLV_RD_STA_DONE_EN (BIT(7)) 182 | #define SPI_SLV_WR_BUF_DONE_EN (BIT(6)) 183 | #define SPI_SLV_RD_BUF_DONE_EN (BIT(5)) 184 | #define SLV_SPI_INT_EN 0x0000001f 185 | #define SLV_SPI_INT_EN_S 5 186 | #define SPI_TRANS_DONE (BIT(4)) 187 | #define SPI_SLV_WR_STA_DONE (BIT(3)) 188 | #define SPI_SLV_RD_STA_DONE (BIT(2)) 189 | #define SPI_SLV_WR_BUF_DONE (BIT(1)) 190 | #define SPI_SLV_RD_BUF_DONE (BIT(0)) 191 | 192 | #define SPI_SLAVE1(i) (REG_SPI_BASE(i) + 0x34) 193 | #define SPI_SLV_STATUS_BITLEN 0x0000001F 194 | #define SPI_SLV_STATUS_BITLEN_S 27 195 | #define SPI_SLV_STATUS_FAST_EN (BIT(26)) //From previous SDK 196 | #define SPI_SLV_STATUS_READBACK (BIT(25)) //From previous SDK 197 | #define SPI_SLV_BUF_BITLEN 0x000001FF 198 | #define SPI_SLV_BUF_BITLEN_S 16 199 | #define SPI_SLV_RD_ADDR_BITLEN 0x0000003F 200 | #define SPI_SLV_RD_ADDR_BITLEN_S 10 201 | #define SPI_SLV_WR_ADDR_BITLEN 0x0000003F 202 | #define SPI_SLV_WR_ADDR_BITLEN_S 4 203 | #define SPI_SLV_WRSTA_DUMMY_EN (BIT(3)) 204 | #define SPI_SLV_RDSTA_DUMMY_EN (BIT(2)) 205 | #define SPI_SLV_WRBUF_DUMMY_EN (BIT(1)) 206 | #define SPI_SLV_RDBUF_DUMMY_EN (BIT(0)) 207 | 208 | 209 | 210 | #define SPI_SLAVE2(i) (REG_SPI_BASE(i) + 0x38) 211 | #define SPI_SLV_WRBUF_DUMMY_CYCLELEN 0X000000FF 212 | #define SPI_SLV_WRBUF_DUMMY_CYCLELEN_S 24 213 | #define SPI_SLV_RDBUF_DUMMY_CYCLELEN 0X000000FF 214 | #define SPI_SLV_RDBUF_DUMMY_CYCLELEN_S 16 215 | #define SPI_SLV_WRSTR_DUMMY_CYCLELEN 0X000000FF 216 | #define SPI_SLV_WRSTR_DUMMY_CYCLELEN_S 8 217 | #define SPI_SLV_RDSTR_DUMMY_CYCLELEN 0x000000FF 218 | #define SPI_SLV_RDSTR_DUMMY_CYCLELEN_S 0 219 | 220 | #define SPI_SLAVE3(i) (REG_SPI_BASE(i) + 0x3C) 221 | #define SPI_SLV_WRSTA_CMD_VALUE 0x000000FF 222 | #define SPI_SLV_WRSTA_CMD_VALUE_S 24 223 | #define SPI_SLV_RDSTA_CMD_VALUE 0x000000FF 224 | #define SPI_SLV_RDSTA_CMD_VALUE_S 16 225 | #define SPI_SLV_WRBUF_CMD_VALUE 0x000000FF 226 | #define SPI_SLV_WRBUF_CMD_VALUE_S 8 227 | #define SPI_SLV_RDBUF_CMD_VALUE 0x000000FF 228 | #define SPI_SLV_RDBUF_CMD_VALUE_S 0 229 | 230 | //Previous SDKs referred to these following registers as SPI_C0 etc. 231 | 232 | #define SPI_W0(i) (REG_SPI_BASE(i) +0x40) 233 | #define SPI_W1(i) (REG_SPI_BASE(i) +0x44) 234 | #define SPI_W2(i) (REG_SPI_BASE(i) +0x48) 235 | #define SPI_W3(i) (REG_SPI_BASE(i) +0x4C) 236 | #define SPI_W4(i) (REG_SPI_BASE(i) +0x50) 237 | #define SPI_W5(i) (REG_SPI_BASE(i) +0x54) 238 | #define SPI_W6(i) (REG_SPI_BASE(i) +0x58) 239 | #define SPI_W7(i) (REG_SPI_BASE(i) +0x5C) 240 | #define SPI_W8(i) (REG_SPI_BASE(i) +0x60) 241 | #define SPI_W9(i) (REG_SPI_BASE(i) +0x64) 242 | #define SPI_W10(i) (REG_SPI_BASE(i) +0x68) 243 | #define SPI_W11(i) (REG_SPI_BASE(i) +0x6C) 244 | #define SPI_W12(i) (REG_SPI_BASE(i) +0x70) 245 | #define SPI_W13(i) (REG_SPI_BASE(i) +0x74) 246 | #define SPI_W14(i) (REG_SPI_BASE(i) +0x78) 247 | #define SPI_W15(i) (REG_SPI_BASE(i) +0x7C) 248 | 249 | // +0x80 to +0xBC could be SPI_W16 through SPI_W31? 250 | 251 | // +0xC0 to +0xEC not currently defined. 252 | 253 | #define SPI_EXT0(i) (REG_SPI_BASE(i) + 0xF0) //From previous SDK. Removed _FLASH_ from name to match other registers. 254 | #define SPI_T_PP_ENA (BIT(31)) //From previous SDK 255 | #define SPI_T_PP_SHIFT 0x0000000F //From previous SDK 256 | #define SPI_T_PP_SHIFT_S 16 //From previous SDK 257 | #define SPI_T_PP_TIME 0x00000FFF //From previous SDK 258 | #define SPI_T_PP_TIME_S 0 //From previous SDK 259 | 260 | #define SPI_EXT1(i) (REG_SPI_BASE(i) + 0xF4) //From previous SDK. Removed _FLASH_ from name to match other registers. 261 | #define SPI_T_ERASE_ENA (BIT(31)) //From previous SDK 262 | #define SPI_T_ERASE_SHIFT 0x0000000F //From previous SDK 263 | #define SPI_T_ERASE_SHIFT_S 16 //From previous SDK 264 | #define SPI_T_ERASE_TIME 0x00000FFF //From previous SDK 265 | #define SPI_T_ERASE_TIME_S 0 //From previous SDK 266 | 267 | #define SPI_EXT2(i) (REG_SPI_BASE(i) + 0xF8) //From previous SDK. Removed _FLASH_ from name to match other registers. 268 | #define SPI_ST 0x00000007 //From previous SDK 269 | #define SPI_ST_S 0 //From previous SDK 270 | 271 | #define SPI_EXT3(i) (REG_SPI_BASE(i) + 0xFC) 272 | #define SPI_INT_HOLD_ENA 0x00000003 273 | #define SPI_INT_HOLD_ENA_S 0 274 | #endif // SPI_REGISTER_H_INCLUDED 275 | -------------------------------------------------------------------------------- /include/user_config.h: -------------------------------------------------------------------------------- 1 | #ifndef __USER_CONFIG_H__ 2 | #define __USER_CONFIG_H__ 3 | 4 | 5 | #endif 6 | -------------------------------------------------------------------------------- /user/user_main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2015 David Ogilvy (MetalPhreak) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | 26 | 27 | #include "osapi.h" 28 | #include "c_types.h" 29 | #include "mem.h" 30 | #include "ets_sys.h" 31 | #include "gpio.h" 32 | #include "os_type.h" 33 | #include "user_interface.h" 34 | #include "espconn.h" 35 | #include "driver/spi.h" 36 | #include "driver/spi_register.h" 37 | #include "driver/mcp23s17.h" 38 | 39 | #define TopTaskPrio 2 40 | #define TopTaskQueueLen 1 41 | 42 | #define ActionTaskPrio 1 43 | #define ActionTaskQueueLen 8 44 | 45 | #define IdleTaskPrio 0 46 | #define IdleTaskQueueLen 1 47 | 48 | #define SSID "Your_AP_SSID" 49 | #define SSID_PASSWORD "Your_AP_Password" 50 | 51 | #define AP_SSID "GPIO16_" //SoftAP SSID 52 | #define AP_SSID_PASSWORD "ESP8266WIFI" //SoftAP SSID 53 | #define AP_CHANNEL 1 //SoftAP Channel 54 | #define AP_AUTH AUTH_WPA_WPA2_PSK //SoftAP Encryption 55 | 56 | static void TopTask(os_event_t *events); 57 | static void ActionTask(os_event_t *events); 58 | static void IdleTask(os_event_t *events); 59 | static void apList(void *arg, STATUS status); 60 | static void tcp_recv(void *arg, char *pdata, unsigned short len); 61 | static void station_init(void); 62 | static void softap_init(uint8 channel); 63 | static void wifi_event_cb(System_Event_t *evt); 64 | 65 | os_event_t TopTaskQueue[TopTaskQueueLen]; 66 | os_event_t ActionTaskQueue[ActionTaskQueueLen]; 67 | os_event_t IdleTaskQueue[IdleTaskQueueLen]; 68 | 69 | uint16 portval = 0; 70 | 71 | static struct espconn *TCP_Server; 72 | 73 | #define TCP_PORT 33333 74 | #define SERVER_TIMEOUT 60 75 | #define MAX_CONNS 5 76 | 77 | 78 | 79 | static void ICACHE_FLASH_ATTR TopTask(os_event_t *events){ 80 | 81 | 82 | } 83 | 84 | static void ICACHE_FLASH_ATTR ActionTask(os_event_t *events){ 85 | 86 | 87 | } 88 | 89 | static void ICACHE_FLASH_ATTR IdleTask(os_event_t *events){ 90 | 91 | 92 | //Add task to add IdleTask back to the queue 93 | system_os_post(IdleTaskPrio, 0, 0); 94 | } 95 | 96 | 97 | void ICACHE_FLASH_ATTR tcp_recv(void *arg, char *pdata, unsigned short len){ 98 | if(len == 2){ 99 | uint16 gpiodata = pdata[0]<<8|pdata[1]; 100 | sGPIO_SET(PORT0, gpiodata); 101 | } 102 | } 103 | 104 | void ICACHE_FLASH_ATTR task_init(void) 105 | { 106 | system_os_task(TopTask, TopTaskPrio, TopTaskQueue, TopTaskQueueLen); 107 | system_os_task(ActionTask, ActionTaskPrio, ActionTaskQueue, ActionTaskQueueLen); 108 | system_os_task(IdleTask, IdleTaskPrio, IdleTaskQueue, IdleTaskQueueLen); 109 | 110 | system_os_post(IdleTaskPrio, 0, 0); 111 | } 112 | 113 | void ICACHE_FLASH_ATTR station_init(void) 114 | { 115 | uint8 ssid[32] = SSID; 116 | uint8 password[64] = SSID_PASSWORD; 117 | struct station_config stationConf; 118 | os_memcpy(&stationConf.ssid, ssid, 32); 119 | os_memcpy(&stationConf.password, password, 64); 120 | wifi_station_set_config(&stationConf); 121 | wifi_set_event_handler_cb(wifi_event_cb); 122 | } 123 | 124 | void ICACHE_FLASH_ATTR wifi_event_cb(System_Event_t *evt) 125 | { 126 | uint8 newchannel = 0; 127 | switch (evt->event) { 128 | case EVENT_STAMODE_CONNECTED: //When connected to AP, change SoftAP to same channel to keep DHCPS working 129 | newchannel = evt->event_info.connected.channel; 130 | softap_init(newchannel); 131 | break; 132 | } 133 | 134 | } 135 | 136 | void ICACHE_FLASH_ATTR softap_init(uint8 channel) 137 | { 138 | uint8 ap_ssid[32]; 139 | uint8 ap_password[64]; 140 | uint8 ap_channel = channel; 141 | uint8 ap_auth = AP_AUTH; 142 | uint8 ap_mac[6]; 143 | wifi_get_macaddr(SOFTAP_IF, ap_mac); 144 | os_sprintf(ap_ssid, "%s%02X%02X%02X%02X%02X%02X\n", AP_SSID, ap_mac[0], ap_mac[1], ap_mac[2], ap_mac[3], ap_mac[4], ap_mac[5]); 145 | struct softap_config softapConf; 146 | os_memcpy(&softapConf.ssid, ap_ssid, strlen(ap_ssid)); 147 | os_sprintf(ap_password, "%s", AP_SSID_PASSWORD); 148 | os_memcpy(&softapConf.password, ap_password, strlen(ap_password)); 149 | //os_printf("MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", ap_mac[0],ap_mac[1],ap_mac[2],ap_mac[3],ap_mac[4],ap_mac[5]); 150 | softapConf.channel = ap_channel; 151 | softapConf.authmode = ap_auth; 152 | softapConf.max_connection = 4; 153 | softapConf.beacon_interval = 100; 154 | wifi_softap_set_config(&softapConf); 155 | 156 | wifi_softap_dhcps_stop(); 157 | struct dhcps_lease dhcp_lease; 158 | IP4_ADDR(&dhcp_lease.start_ip, 192, 168, 5, 2); 159 | IP4_ADDR(&dhcp_lease.end_ip, 192, 168, 5, 100); 160 | wifi_softap_set_dhcps_lease(&dhcp_lease); 161 | struct ip_info info; 162 | IP4_ADDR(&info.ip, 192, 168, 5, 1); 163 | IP4_ADDR(&info.gw, 192, 168, 5, 1); 164 | IP4_ADDR(&info.netmask, 255, 255, 255, 0); 165 | wifi_set_ip_info(SOFTAP_IF, &info); 166 | wifi_softap_dhcps_start(); 167 | } 168 | 169 | void user_init(void) 170 | { 171 | wifi_set_opmode(0x03); //0x01 Station mode, 0x02 Soft-AP, 0x03 Combined Mode 172 | 173 | softap_init(AP_CHANNEL); 174 | station_init(); 175 | 176 | mcp23s17_init(); 177 | mcp23s17_REG_SET(IODIR_CTRL, PORT0, 0x0000); //setup all GPIO pins as outputs 178 | 179 | TCP_Server = (struct espconn *)os_zalloc(sizeof(struct espconn)); 180 | TCP_Server->type = ESPCONN_TCP; 181 | TCP_Server->state = ESPCONN_NONE; 182 | TCP_Server->proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp)); 183 | TCP_Server->proto.tcp->local_port = TCP_PORT; 184 | espconn_regist_recvcb(TCP_Server, tcp_recv); 185 | espconn_accept(TCP_Server); 186 | espconn_regist_time(TCP_Server, SERVER_TIMEOUT, 0); 187 | 188 | task_init(); 189 | } 190 | 191 | 192 | 193 | 194 | --------------------------------------------------------------------------------