From 6b1746e2f118ebe023e98cc8ae0123e53b7b3817 Mon Sep 17 00:00:00 2001 From: LongHairedHacker Date: Mon, 14 Sep 2015 21:03:29 +0200 Subject: [PATCH] Initial commit. DMX works for some full circle boxes --- .gitignore | 8 + .gitmodules | 3 + Makefile | 216 +++++++++++++++++++++++ driver/Makefile | 44 +++++ driver/uart.c | 312 +++++++++++++++++++++++++++++++++ include/debug.h | 15 ++ include/driver/uart.h | 104 +++++++++++ include/driver/uart_register.h | 128 ++++++++++++++ include/user_config.h | 10 ++ modules/Makefile | 44 +++++ modules/include/pin_map.h | 71 ++++++++ modules/include/wifi.h | 15 ++ modules/pin_map.c | 30 ++++ modules/wifi.c | 97 ++++++++++ twinkl | 1 + user/Makefile | 44 +++++ user/user_main.c | 136 ++++++++++++++ 17 files changed, 1278 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 Makefile create mode 100644 driver/Makefile create mode 100644 driver/uart.c create mode 100644 include/debug.h create mode 100644 include/driver/uart.h create mode 100644 include/driver/uart_register.h create mode 100644 include/user_config.h create mode 100644 modules/Makefile create mode 100644 modules/include/pin_map.h create mode 100644 modules/include/wifi.h create mode 100644 modules/pin_map.c create mode 100644 modules/wifi.c create mode 160000 twinkl create mode 100644 user/Makefile create mode 100644 user/user_main.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..70674ba --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +*.swp +*.swo +*.bak + +*.o +*.bin +*.a +*.out diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..87ca985 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "twinkl"] + path = twinkl + url = git@github.com:LongHairedHacker/twinkl.git diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..93a3c11 --- /dev/null +++ b/Makefile @@ -0,0 +1,216 @@ +# Changelog +# Changed the variables to include the header file directory +# Added global var for the XTENSA tool root +# +# This make file still needs some work. +# +# +# Output directors to store intermediate compiled files +# relative to the project directory +BUILD_BASE = build +FW_BASE = firmware +ESPTOOL = esptool.py + + +# name for the target project +TARGET = app + +# linker script used for the above linkier step +LD_SCRIPT = eagle.app.v6.ld + +# we create two different files for uploading into the flash +# these are the names and options to generate them +FW_1 = 0x00000 +FW_2 = 0x40000 + +FLAVOR ?= release + + +############################################################# +# Select compile +# +ifeq ($(OS),Windows_NT) +# WIN32 +# We are under windows. + ifeq ($(XTENSA_CORE),lx106) + # It is xcc + AR = xt-ar + CC = xt-xcc + LD = xt-xcc + NM = xt-nm + CPP = xt-cpp + OBJCOPY = xt-objcopy + #MAKE = xt-make + CCFLAGS += -Os --rename-section .text=.irom0.text --rename-section .literal=.irom0.literal + else + # It is gcc, may be cygwin + # Can we use -fdata-sections? + CCFLAGS += -Os -ffunction-sections -fno-jump-tables + AR = xtensa-lx106-elf-ar + CC = xtensa-lx106-elf-gcc + LD = xtensa-lx106-elf-gcc + NM = xtensa-lx106-elf-nm + CPP = xtensa-lx106-elf-cpp + OBJCOPY = xtensa-lx106-elf-objcopy + endif + ESPPORT ?= com1 + SDK_BASE ?= c:/Espressif/ESP8266_SDK + ifeq ($(PROCESSOR_ARCHITECTURE),AMD64) +# ->AMD64 + endif + ifeq ($(PROCESSOR_ARCHITECTURE),x86) +# ->IA32 + endif +else +# We are under other system, may be Linux. Assume using gcc. + # Can we use -fdata-sections? + ESPPORT ?= /dev/ttyUSB0 + SDK_BASE ?= /home/sebastian/projects/esp8266/esp-open-sdk/sdk + + CCFLAGS += -Os -ffunction-sections -fno-jump-tables + AR = xtensa-lx106-elf-ar + CC = xtensa-lx106-elf-gcc + LD = xtensa-lx106-elf-gcc + NM = xtensa-lx106-elf-nm + CPP = xtensa-lx106-elf-cpp + OBJCOPY = xtensa-lx106-elf-objcopy + UNAME_S := $(shell uname -s) + + ifeq ($(UNAME_S),Linux) +# LINUX + endif + ifeq ($(UNAME_S),Darwin) +# OSX + endif + UNAME_P := $(shell uname -p) + ifeq ($(UNAME_P),x86_64) +# ->AMD64 + endif + ifneq ($(filter %86,$(UNAME_P)),) +# ->IA32 + endif + ifneq ($(filter arm%,$(UNAME_P)),) +# ->ARM + endif +endif +############################################################# + + +# which modules (subdirectories) of the project to include in compiling +MODULES = twinkl driver user modules +EXTRA_INCDIR = include $(SDK_BASE)/../include + +# libraries used in this project, mainly provided by the SDK +LIBS = c gcc hal phy pp net80211 lwip wpa main ssl + +# compiler flags using during compilation of source files +CFLAGS = -Os -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH + +# linker flags used to generate the main object file +LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static + +ifeq ($(FLAVOR),debug) + CFLAGS += -g -O0 + LDFLAGS += -g -O0 +endif + +ifeq ($(FLAVOR),release) + CFLAGS += -g -O2 + LDFLAGS += -g -O2 +endif + + + +# various paths from the SDK used in this project +SDK_LIBDIR = lib +SDK_LDDIR = ld +SDK_INCDIR = include include/json + +#### +#### no user configurable options below here +#### +FW_TOOL ?= $(ESPTOOL) +SRC_DIR := $(MODULES) +BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES)) + +SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR)) +SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR)) + +SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) +OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) +LIBS := $(addprefix -l,$(LIBS)) +APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a) +TARGET_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).out) + +LD_SCRIPT := $(addprefix -T$(SDK_BASE)/$(SDK_LDDIR)/,$(LD_SCRIPT)) + +INCDIR := $(addprefix -I,$(SRC_DIR)) +EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR)) +MODULE_INCDIR := $(addsuffix /include,$(INCDIR)) + +FW_FILE_1 := $(addprefix $(FW_BASE)/,$(FW_1).bin) +FW_FILE_2 := $(addprefix $(FW_BASE)/,$(FW_2).bin) + +V ?= $(VERBOSE) +ifeq ("$(V)","1") +Q := +vecho := @true +else +Q := @ +vecho := @echo +endif + +vpath %.c $(SRC_DIR) + +define compile-objects +$1/%.o: %.c + $(vecho) "CC $$<" + $(Q) $(CC) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@ +endef + +.PHONY: all checkdirs clean + +all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2) + +$(FW_FILE_1): $(TARGET_OUT) + $(vecho) "FW $@" + $(ESPTOOL) elf2image $< -o $(FW_BASE)/ + +$(FW_FILE_2): $(TARGET_OUT) + $(vecho) "FW $@" + $(ESPTOOL) elf2image $< -o $(FW_BASE)/ + +$(TARGET_OUT): $(APP_AR) + $(vecho) "LD $@" + $(Q) $(LD) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ + +$(APP_AR): $(OBJ) + $(vecho) "AR $@" + $(Q) $(AR) cru $@ $^ + +checkdirs: $(BUILD_DIR) $(FW_BASE) + +$(BUILD_DIR): + $(Q) mkdir -p $@ + +firmware: + $(Q) mkdir -p $@ + +flash: $(FW_FILE_1) $(FW_FILE_2) + $(ESPTOOL) -f write_flash $(FW_2) $(FW_FILE_2) $(FW_1) $(FW_FILE_1) + +test: flash + screen $(ESPPORT) 115200 + +rebuild: clean all + +clean: + $(Q) rm -f $(APP_AR) + $(Q) rm -f $(TARGET_OUT) + $(Q) rm -rf $(BUILD_DIR) + $(Q) rm -rf $(BUILD_BASE) + $(Q) rm -f $(FW_FILE_1) + $(Q) rm -f $(FW_FILE_2) + $(Q) rm -rf $(FW_BASE) + +$(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir)))) diff --git a/driver/Makefile b/driver/Makefile new file mode 100644 index 0000000..38fd29f --- /dev/null +++ b/driver/Makefile @@ -0,0 +1,44 @@ + +############################################################# +# Required variables for each makefile +# Discard this section from all parent makefiles +# Expected variables (with automatic defaults): +# CSRCS (all "C" files in the dir) +# SUBDIRS (all subdirs with a Makefile) +# GEN_LIBS - list of libs to be generated () +# GEN_IMAGES - list of images to be generated () +# COMPONENTS_xxx - a list of libs/objs in the form +# subdir/lib to be extracted and rolled up into +# a generated lib/image xxx.a () +# +ifndef PDIR +GEN_LIBS = libdriver.a +endif + + +############################################################# +# Configuration i.e. compile options etc. +# Target specific stuff (defines etc.) goes in here! +# Generally values applying to a tree are captured in the +# makefile at its root level - these are then overridden +# for a subtree within the makefile rooted therein +# +#DEFINES += + +############################################################# +# Recursion Magic - Don't touch this!! +# +# Each subtree potentially has an include directory +# corresponding to the common APIs applicable to modules +# rooted at that subtree. Accordingly, the INCLUDE PATH +# of a module can only contain the include directories up +# its parent path, and not its siblings +# +# Required for each makefile to inherit from the parent +# + +INCLUDES := $(INCLUDES) -I $(PDIR)include +INCLUDES += -I ./ +PDIR := ../$(PDIR) +sinclude $(PDIR)Makefile + diff --git a/driver/uart.c b/driver/uart.c new file mode 100644 index 0000000..e9a0dff --- /dev/null +++ b/driver/uart.c @@ -0,0 +1,312 @@ +/****************************************************************************** + * Copyright 2013-2014 Espressif Systems (Wuxi) + * + * FileName: uart.c + * + * Description: Two UART mode configration and interrupt handler. + * Check your hardware connection while use this mode. + * + * Modification history: + * 2014/3/12, v1.0 create this file. +*******************************************************************************/ +#include "ets_sys.h" +#include "osapi.h" +#include "driver/uart.h" +#include "osapi.h" +#include "driver/uart_register.h" + + +// UartDev is defined and initialized in rom code. +extern UartDevice UartDev; +//extern os_event_t at_recvTaskQueue[at_recvTaskQueueLen]; + +LOCAL void uart0_rx_intr_handler(void *para); + +/****************************************************************************** + * FunctionName : uart_config + * Description : Internal used function + * UART0 used for data TX/RX, RX buffer size is 0x100, interrupt enabled + * UART1 just used for debug output + * Parameters : uart_no, use UART0 or UART1 defined ahead + * Returns : NONE +*******************************************************************************/ +LOCAL void ICACHE_FLASH_ATTR +uart_config(uint8 uart_no) +{ + if (uart_no == UART1) + { + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK); + } + else + { + /* rcv_buff size if 0x100 */ + ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, &(UartDev.rcv_buff)); + PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS); + } + + uart_div_modify(uart_no, UART_CLK_FREQ / (UartDev.baut_rate)); + + WRITE_PERI_REG(UART_CONF0(uart_no), UartDev.exist_parity + | UartDev.parity + | (UartDev.stop_bits << UART_STOP_BIT_NUM_S) + | (UartDev.data_bits << UART_BIT_NUM_S)); + + //clear rx and tx fifo,not ready + SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST); + CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST); + + //set rx fifo trigger +// WRITE_PERI_REG(UART_CONF1(uart_no), +// ((UartDev.rcv_buff.TrigLvl & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) | +// ((96 & UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S) | +// UART_RX_FLOW_EN); + if (uart_no == UART0) + { + //set rx fifo trigger + WRITE_PERI_REG(UART_CONF1(uart_no), + ((0x10 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) | + ((0x10 & UART_RX_FLOW_THRHD) << UART_RX_FLOW_THRHD_S) | + UART_RX_FLOW_EN | + (0x02 & UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S | + UART_RX_TOUT_EN); + SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_TOUT_INT_ENA | + UART_FRM_ERR_INT_ENA); + } + else + { + WRITE_PERI_REG(UART_CONF1(uart_no), + ((UartDev.rcv_buff.TrigLvl & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S)); + } + + //clear all interrupt + WRITE_PERI_REG(UART_INT_CLR(uart_no), 0xffff); + //enable rx_interrupt + SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA); +} + +/****************************************************************************** + * FunctionName : uart1_tx_one_char + * Description : Internal used function + * Use uart1 interface to transfer one char + * Parameters : uint8 TxChar - character to tx + * Returns : OK +*******************************************************************************/ +STATUS +uart_tx_one_char(uint8 uart, uint8 TxChar) +{ + while (true) + { + uint32 fifo_cnt = READ_PERI_REG(UART_STATUS(uart)) & (UART_TXFIFO_CNT<> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) < 126) { + break; + } + } + + WRITE_PERI_REG(UART_FIFO(uart) , TxChar); + return OK; +} + +/****************************************************************************** + * FunctionName : uart1_write_char + * Description : Internal used function + * Do some special deal while tx char is '\r' or '\n' + * Parameters : char c - character to tx + * Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +uart1_write_char(char c) +{ + if (c == '\n') + { + uart_tx_one_char(UART1, '\r'); + uart_tx_one_char(UART1, '\n'); + } + else if (c == '\r') + { + } + else + { + uart_tx_one_char(UART1, c); + } +} + +void ICACHE_FLASH_ATTR +uart0_write_char(char c) +{ + if (c == '\n') + { + uart_tx_one_char(UART0, '\r'); + uart_tx_one_char(UART0, '\n'); + } + else if (c == '\r') + { + } + else + { + uart_tx_one_char(UART0, c); + } +} +/****************************************************************************** + * FunctionName : uart0_tx_buffer + * Description : use uart0 to transfer buffer + * Parameters : uint8 *buf - point to send buffer + * uint16 len - buffer len + * Returns : +*******************************************************************************/ +void ICACHE_FLASH_ATTR +uart0_tx_buffer(uint8 *buf, uint16 len) +{ + uint16 i; + + for (i = 0; i < len; i++) + { + uart_tx_one_char(UART0, buf[i]); + } +} + +/****************************************************************************** + * FunctionName : uart0_sendStr + * Description : use uart0 to transfer buffer + * Parameters : uint8 *buf - point to send buffer + * uint16 len - buffer len + * Returns : +*******************************************************************************/ +void ICACHE_FLASH_ATTR +uart0_sendStr(const char *str) +{ + while(*str) + { + uart_tx_one_char(UART0, *str++); + } +} + +/****************************************************************************** + * FunctionName : uart0_rx_intr_handler + * Description : Internal used function + * UART0 interrupt handler, add self handle code inside + * Parameters : void *para - point to ETS_UART_INTR_ATTACH's arg + * Returns : NONE +*******************************************************************************/ +//extern void at_recvTask(void); + +LOCAL void +uart0_rx_intr_handler(void *para) +{ + /* uart0 and uart1 intr combine togther, when interrupt occur, see reg 0x3ff20020, bit2, bit0 represents + * uart1 and uart0 respectively + */ +// RcvMsgBuff *pRxBuff = (RcvMsgBuff *)para; + uint8 RcvChar; + uint8 uart_no = UART0;//UartDev.buff_uart_no; + +// if (UART_RXFIFO_FULL_INT_ST != (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST)) +// { +// return; +// } +// if (UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST)) +// { +//// at_recvTask(); +// RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF; +// system_os_post(at_recvTaskPrio, NULL, RcvChar); +// WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR); +// } + if(UART_FRM_ERR_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_FRM_ERR_INT_ST)) + { + os_printf("FRM_ERR\r\n"); + WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_FRM_ERR_INT_CLR); + } + + if(UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST)) + { +// os_printf("fifo full\r\n"); + ETS_UART_INTR_DISABLE();///////// + + //system_os_post(at_recvTaskPrio, 0, 0); + +// WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR); +// while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) +// { +//// at_recvTask(); +// RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF; +// system_os_post(at_recvTaskPrio, NULL, RcvChar); +// } + } + else if(UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_TOUT_INT_ST)) + { + ETS_UART_INTR_DISABLE();///////// + + //system_os_post(at_recvTaskPrio, 0, 0); + +// WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_TOUT_INT_CLR); +//// os_printf("rx time over\r\n"); +// while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) +// { +//// os_printf("process recv\r\n"); +//// at_recvTask(); +// RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF; +// system_os_post(at_recvTaskPrio, NULL, RcvChar); +// } + } + +// WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR); + +// if (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) +// { +// RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF; +// at_recvTask(); +// *(pRxBuff->pWritePos) = RcvChar; + +// system_os_post(at_recvTaskPrio, NULL, RcvChar); + +// //insert here for get one command line from uart +// if (RcvChar == '\r') +// { +// pRxBuff->BuffState = WRITE_OVER; +// } +// +// pRxBuff->pWritePos++; +// +// if (pRxBuff->pWritePos == (pRxBuff->pRcvMsgBuff + RX_BUFF_SIZE)) +// { +// // overflow ...we may need more error handle here. +// pRxBuff->pWritePos = pRxBuff->pRcvMsgBuff ; +// } +// } +} + +/****************************************************************************** + * FunctionName : uart_init + * Description : user interface for init uart + * Parameters : UartBautRate uart0_br - uart0 bautrate + * UartBautRate uart1_br - uart1 bautrate + * Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +uart_init(UartBautRate uart0_br, UartBautRate uart1_br) +{ + UartDev.data_bits = EIGHT_BITS; + UartDev.exist_parity = STICK_PARITY_DIS; + UartDev.parity = NONE_BITS; + UartDev.flow_ctrl = NONE_CTRL; + + // rom use 74880 baut_rate, here reinitialize + UartDev.baut_rate = uart0_br; + uart_config(UART0); + UartDev.baut_rate = uart1_br; + UartDev.stop_bits = TWO_STOP_BIT; + uart_config(UART1); + ETS_UART_INTR_ENABLE(); + + // install uart1 putc callback + os_install_putc1((void *)uart0_write_char); +} + +void ICACHE_FLASH_ATTR +uart_reattach() +{ + uart_init(BIT_RATE_74880, BIT_RATE_74880); +// ETS_UART_INTR_ATTACH(uart_rx_intr_handler_ssc, &(UartDev.rcv_buff)); +// ETS_UART_INTR_ENABLE(); +} diff --git a/include/debug.h b/include/debug.h new file mode 100644 index 0000000..d2c430a --- /dev/null +++ b/include/debug.h @@ -0,0 +1,15 @@ +/* + * debug.h + * + * Created on: Dec 4, 2014 + * Author: Minh + */ + +#ifndef USER_DEBUG_H_ +#define USER_DEBUG_H_ + +#ifndef INFO +#define INFO os_printf +#endif + +#endif /* USER_DEBUG_H_ */ diff --git a/include/driver/uart.h b/include/driver/uart.h new file mode 100644 index 0000000..817a0ca --- /dev/null +++ b/include/driver/uart.h @@ -0,0 +1,104 @@ +#ifndef UART_APP_H +#define UART_APP_H + +#include "uart_register.h" +#include "eagle_soc.h" +#include "c_types.h" + +#define RX_BUFF_SIZE 256 +#define TX_BUFF_SIZE 100 +#define UART0 0 +#define UART1 1 + +typedef enum { + FIVE_BITS = 0x0, + SIX_BITS = 0x1, + SEVEN_BITS = 0x2, + EIGHT_BITS = 0x3 +} UartBitsNum4Char; + +typedef enum { + ONE_STOP_BIT = 0, + ONE_HALF_STOP_BIT = BIT2, + TWO_STOP_BIT = BIT2 +} UartStopBitsNum; + +typedef enum { + NONE_BITS = 0, + ODD_BITS = 0, + EVEN_BITS = BIT4 +} UartParityMode; + +typedef enum { + STICK_PARITY_DIS = 0, + STICK_PARITY_EN = BIT3 | BIT5 +} UartExistParity; + +typedef enum { + BIT_RATE_9600 = 9600, + BIT_RATE_19200 = 19200, + BIT_RATE_38400 = 38400, + BIT_RATE_57600 = 57600, + BIT_RATE_74880 = 74880, + BIT_RATE_115200 = 115200, + BIT_RATE_230400 = 230400, + BIT_RATE_256000 = 256000, + BIT_RATE_250000 = 250000, + BIT_RATE_460800 = 460800, + BIT_RATE_921600 = 921600 +} UartBautRate; + +typedef enum { + NONE_CTRL, + HARDWARE_CTRL, + XON_XOFF_CTRL +} UartFlowCtrl; + +typedef enum { + EMPTY, + UNDER_WRITE, + WRITE_OVER +} RcvMsgBuffState; + +typedef struct { + uint32 RcvBuffSize; + uint8 *pRcvMsgBuff; + uint8 *pWritePos; + uint8 *pReadPos; + uint8 TrigLvl; //JLU: may need to pad + RcvMsgBuffState BuffState; +} RcvMsgBuff; + +typedef struct { + uint32 TrxBuffSize; + uint8 *pTrxBuff; +} TrxMsgBuff; + +typedef enum { + BAUD_RATE_DET, + WAIT_SYNC_FRM, + SRCH_MSG_HEAD, + RCV_MSG_BODY, + RCV_ESC_CHAR, +} RcvMsgState; + +typedef struct { + UartBautRate baut_rate; + UartBitsNum4Char data_bits; + UartExistParity exist_parity; + UartParityMode parity; // chip size in byte + UartStopBitsNum stop_bits; + UartFlowCtrl flow_ctrl; + RcvMsgBuff rcv_buff; + TrxMsgBuff trx_buff; + RcvMsgState rcv_state; + int received; + int buff_uart_no; //indicate which uart use tx/rx buffer +} UartDevice; + +void uart_init(UartBautRate uart0_br, UartBautRate uart1_br); +void uart0_sendStr(const char *str); + +STATUS uart_tx_one_char(uint8 uart, uint8 TxChar); +#endif + diff --git a/include/driver/uart_register.h b/include/driver/uart_register.h new file mode 100644 index 0000000..6398879 --- /dev/null +++ b/include/driver/uart_register.h @@ -0,0 +1,128 @@ +//Generated at 2012-07-03 18:44:06 +/* + * Copyright (c) 2010 - 2011 Espressif System + * + */ + +#ifndef UART_REGISTER_H_INCLUDED +#define UART_REGISTER_H_INCLUDED +#define REG_UART_BASE( i ) (0x60000000+(i)*0xf00) +//version value:32'h062000 + +#define UART_FIFO( i ) (REG_UART_BASE( i ) + 0x0) +#define UART_RXFIFO_RD_BYTE 0x000000FF +#define UART_RXFIFO_RD_BYTE_S 0 + +#define UART_INT_RAW( i ) (REG_UART_BASE( i ) + 0x4) +#define UART_RXFIFO_TOUT_INT_RAW (BIT(8)) +#define UART_BRK_DET_INT_RAW (BIT(7)) +#define UART_CTS_CHG_INT_RAW (BIT(6)) +#define UART_DSR_CHG_INT_RAW (BIT(5)) +#define UART_RXFIFO_OVF_INT_RAW (BIT(4)) +#define UART_FRM_ERR_INT_RAW (BIT(3)) +#define UART_PARITY_ERR_INT_RAW (BIT(2)) +#define UART_TXFIFO_EMPTY_INT_RAW (BIT(1)) +#define UART_RXFIFO_FULL_INT_RAW (BIT(0)) + +#define UART_INT_ST( i ) (REG_UART_BASE( i ) + 0x8) +#define UART_RXFIFO_TOUT_INT_ST (BIT(8)) +#define UART_BRK_DET_INT_ST (BIT(7)) +#define UART_CTS_CHG_INT_ST (BIT(6)) +#define UART_DSR_CHG_INT_ST (BIT(5)) +#define UART_RXFIFO_OVF_INT_ST (BIT(4)) +#define UART_FRM_ERR_INT_ST (BIT(3)) +#define UART_PARITY_ERR_INT_ST (BIT(2)) +#define UART_TXFIFO_EMPTY_INT_ST (BIT(1)) +#define UART_RXFIFO_FULL_INT_ST (BIT(0)) + +#define UART_INT_ENA( i ) (REG_UART_BASE( i ) + 0xC) +#define UART_RXFIFO_TOUT_INT_ENA (BIT(8)) +#define UART_BRK_DET_INT_ENA (BIT(7)) +#define UART_CTS_CHG_INT_ENA (BIT(6)) +#define UART_DSR_CHG_INT_ENA (BIT(5)) +#define UART_RXFIFO_OVF_INT_ENA (BIT(4)) +#define UART_FRM_ERR_INT_ENA (BIT(3)) +#define UART_PARITY_ERR_INT_ENA (BIT(2)) +#define UART_TXFIFO_EMPTY_INT_ENA (BIT(1)) +#define UART_RXFIFO_FULL_INT_ENA (BIT(0)) + +#define UART_INT_CLR( i ) (REG_UART_BASE( i ) + 0x10) +#define UART_RXFIFO_TOUT_INT_CLR (BIT(8)) +#define UART_BRK_DET_INT_CLR (BIT(7)) +#define UART_CTS_CHG_INT_CLR (BIT(6)) +#define UART_DSR_CHG_INT_CLR (BIT(5)) +#define UART_RXFIFO_OVF_INT_CLR (BIT(4)) +#define UART_FRM_ERR_INT_CLR (BIT(3)) +#define UART_PARITY_ERR_INT_CLR (BIT(2)) +#define UART_TXFIFO_EMPTY_INT_CLR (BIT(1)) +#define UART_RXFIFO_FULL_INT_CLR (BIT(0)) + +#define UART_CLKDIV( i ) (REG_UART_BASE( i ) + 0x14) +#define UART_CLKDIV_CNT 0x000FFFFF +#define UART_CLKDIV_S 0 + +#define UART_AUTOBAUD( i ) (REG_UART_BASE( i ) + 0x18) +#define UART_GLITCH_FILT 0x000000FF +#define UART_GLITCH_FILT_S 8 +#define UART_AUTOBAUD_EN (BIT(0)) + +#define UART_STATUS( i ) (REG_UART_BASE( i ) + 0x1C) +#define UART_TXD (BIT(31)) +#define UART_RTSN (BIT(30)) +#define UART_DTRN (BIT(29)) +#define UART_TXFIFO_CNT 0x000000FF +#define UART_TXFIFO_CNT_S 16 +#define UART_RXD (BIT(15)) +#define UART_CTSN (BIT(14)) +#define UART_DSRN (BIT(13)) +#define UART_RXFIFO_CNT 0x000000FF +#define UART_RXFIFO_CNT_S 0 + +#define UART_CONF0( i ) (REG_UART_BASE( i ) + 0x20) +#define UART_TXFIFO_RST (BIT(18)) +#define UART_RXFIFO_RST (BIT(17)) +#define UART_IRDA_EN (BIT(16)) +#define UART_TX_FLOW_EN (BIT(15)) +#define UART_LOOPBACK (BIT(14)) +#define UART_IRDA_RX_INV (BIT(13)) +#define UART_IRDA_TX_INV (BIT(12)) +#define UART_IRDA_WCTL (BIT(11)) +#define UART_IRDA_TX_EN (BIT(10)) +#define UART_IRDA_DPLX (BIT(9)) +#define UART_TXD_BRK (BIT(8)) +#define UART_SW_DTR (BIT(7)) +#define UART_SW_RTS (BIT(6)) +#define UART_STOP_BIT_NUM 0x00000003 +#define UART_STOP_BIT_NUM_S 4 +#define UART_BIT_NUM 0x00000003 +#define UART_BIT_NUM_S 2 +#define UART_PARITY_EN (BIT(1)) +#define UART_PARITY (BIT(0)) + +#define UART_CONF1( i ) (REG_UART_BASE( i ) + 0x24) +#define UART_RX_TOUT_EN (BIT(31)) +#define UART_RX_TOUT_THRHD 0x0000007F +#define UART_RX_TOUT_THRHD_S 24 +#define UART_RX_FLOW_EN (BIT(23)) +#define UART_RX_FLOW_THRHD 0x0000007F +#define UART_RX_FLOW_THRHD_S 16 +#define UART_TXFIFO_EMPTY_THRHD 0x0000007F +#define UART_TXFIFO_EMPTY_THRHD_S 8 +#define UART_RXFIFO_FULL_THRHD 0x0000007F +#define UART_RXFIFO_FULL_THRHD_S 0 + +#define UART_LOWPULSE( i ) (REG_UART_BASE( i ) + 0x28) +#define UART_LOWPULSE_MIN_CNT 0x000FFFFF +#define UART_LOWPULSE_MIN_CNT_S 0 + +#define UART_HIGHPULSE( i ) (REG_UART_BASE( i ) + 0x2C) +#define UART_HIGHPULSE_MIN_CNT 0x000FFFFF +#define UART_HIGHPULSE_MIN_CNT_S 0 + +#define UART_PULSE_NUM( i ) (REG_UART_BASE( i ) + 0x30) +#define UART_PULSE_NUM_CNT 0x0003FF +#define UART_PULSE_NUM_CNT_S 0 + +#define UART_DATE( i ) (REG_UART_BASE( i ) + 0x78) +#define UART_ID( i ) (REG_UART_BASE( i ) + 0x7C) +#endif // UART_REGISTER_H_INCLUDED diff --git a/include/user_config.h b/include/user_config.h new file mode 100644 index 0000000..a5773bc --- /dev/null +++ b/include/user_config.h @@ -0,0 +1,10 @@ +#ifndef _USER_CONFIG_ +#define _USER_CONFIG_ + +#include + +static const char wifi_ssid[] = ""; +static const char wifi_password[] = ""; +static const const uint16_t udp_port = 1337; + +#endif diff --git a/modules/Makefile b/modules/Makefile new file mode 100644 index 0000000..db53f43 --- /dev/null +++ b/modules/Makefile @@ -0,0 +1,44 @@ + +############################################################# +# Required variables for each makefile +# Discard this section from all parent makefiles +# Expected variables (with automatic defaults): +# CSRCS (all "C" files in the dir) +# SUBDIRS (all subdirs with a Makefile) +# GEN_LIBS - list of libs to be generated () +# GEN_IMAGES - list of images to be generated () +# COMPONENTS_xxx - a list of libs/objs in the form +# subdir/lib to be extracted and rolled up into +# a generated lib/image xxx.a () +# +ifndef PDIR +GEN_LIBS = libmqtt.a +endif + + +############################################################# +# Configuration i.e. compile options etc. +# Target specific stuff (defines etc.) goes in here! +# Generally values applying to a tree are captured in the +# makefile at its root level - these are then overridden +# for a subtree within the makefile rooted therein +# +#DEFINES += + +############################################################# +# Recursion Magic - Don't touch this!! +# +# Each subtree potentially has an include directory +# corresponding to the common APIs applicable to modules +# rooted at that subtree. Accordingly, the INCLUDE PATH +# of a module can only contain the include directories up +# its parent path, and not its siblings +# +# Required for each makefile to inherit from the parent +# + +INCLUDES := $(INCLUDES) -I $(PDIR)include +INCLUDES += -I ./ +PDIR := ../$(PDIR) +sinclude $(PDIR)Makefile + diff --git a/modules/include/pin_map.h b/modules/include/pin_map.h new file mode 100644 index 0000000..db9f6d1 --- /dev/null +++ b/modules/include/pin_map.h @@ -0,0 +1,71 @@ +/* + * Copied from esp8266-frankenstein + * https://github.com/nekromant/esp8266-frankenstein/blob/master/include/pin_map.h + * + * + * There is not a 1:1 mapping between physical pin numbers numbers and the + * various constants uses to control GPIO functionality. + * + * The following globals are used to make this easy without adding masses of + * overhead that a fully fledged abstraction library (such as that provided by + * Arduino) might add: + * + * pin_mux[gpio] ->> returns the correct constant for gpio 'pin' to use + * as the first argument to PIN_FUNC_SELECT(), + * PIN_PULLDWN_DIS(), PIN_PULLUP_DIS(), PIN_PULLUP_EN(), + * PIN_PULLDWN_DIS() functions + * + * pin_func[gpio] ->> returns the correct constant for gpio 'gpio' to use + * as the second argument to PIN_FUNC_SELECT() + * + * The gpio is passed directly to GPIO_DIS_OUTPUT(), GPIO_OUTPUT_SET() and + * GPIO_OUTPUT_GET() + * + * pin_int_type[gpio] is used to return the GPIO_PIN_INTR_DISABLE state when + * GPIO interrupts are enabled. + * + * The actual mappings are described in the file pin_map.c + * + * Not all gpio numbers are valid. This can be checked first using the function + * is_valid_gpio_pin() which also checks for the gpio in the range + * 0..GPIO_PIN_NUM-1 + * + * Invalid gpio will also report -1 for pin_mux[] and pin_func[] + * + * Note that the ESP SDK provides an additional macro, GPIO_ID_PIN() which in + * theory should be wrapped around all 'gpio' numbers passed to the register + * functions, however, this macro essentially resolves to a NO-OP so code will + * work fine without it. It is not inconceivable however that there could be + * a future hardware version increment that breaks this, so I guess omit this + * at your own risk. + * + * EXAMPLE + * ------- + * + * uint8_t gpio = argv[2]; + * if (!is_valid_gpio_pin(gpio)) { printf("error...\n"); return; } + * PIN_FUNC_SELECT(pin_mux[gpio], pin_func[gpio]); + * PIN_PULLDWN_DIS(pin_mux[gpio]); + * GPIO_DIS_OUTPUT(GPIO_ID_PIN(gpio)); + * + */ +#ifndef __PIN_MAP_H__ +#define __PIN_MAP_H__ + +#include "c_types.h" +#include "user_config.h" +#include "gpio.h" + +#define GPIO_PIN_NUM 17 +#define GPIO_PIN_FUNC_INVALID (uint8_t)(-1) +#define GPIO_PIN_MUX_INVALID (uint32_t)(-1) + +extern bool is_valid_gpio_pin(uint8 gpiopin); + +//extern uint8_t pin_num[GPIO_PIN_NUM]; +extern uint8_t pin_func[GPIO_PIN_NUM]; +extern uint32_t pin_mux[GPIO_PIN_NUM]; +#ifdef GPIO_INTERRUPT_ENABLE +extern GPIO_INT_TYPE pin_int_type[GPIO_PIN_NUM]; +#endif +#endif // #ifndef __PIN_MAP_H__ diff --git a/modules/include/wifi.h b/modules/include/wifi.h new file mode 100644 index 0000000..3b96c03 --- /dev/null +++ b/modules/include/wifi.h @@ -0,0 +1,15 @@ +/* + * wifi.h + * + * Created on: Dec 30, 2014 + * Author: Minh + */ + +#ifndef USER_WIFI_H_ +#define USER_WIFI_H_ +#include "os_type.h" +typedef void (*WifiCallback)(uint8_t); +void ICACHE_FLASH_ATTR WIFI_Connect(const uint8_t* ssid, const uint8_t* pass, WifiCallback cb); + + +#endif /* USER_WIFI_H_ */ diff --git a/modules/pin_map.c b/modules/pin_map.c new file mode 100644 index 0000000..7521ca1 --- /dev/null +++ b/modules/pin_map.c @@ -0,0 +1,30 @@ +/* + * Copied from esp8266-frankenstein + * https://github.com/nekromant/esp8266-frankenstein/blob/master/src/pin_map.c + */ + +#include "pin_map.h" +#include "eagle_soc.h" + +uint32_t pin_mux[GPIO_PIN_NUM] = { + PERIPHS_IO_MUX_GPIO0_U, PERIPHS_IO_MUX_U0TXD_U, PERIPHS_IO_MUX_GPIO2_U, PERIPHS_IO_MUX_U0RXD_U, + PERIPHS_IO_MUX_GPIO4_U, PERIPHS_IO_MUX_GPIO5_U, -1, -1, + -1, PERIPHS_IO_MUX_SD_DATA2_U, PERIPHS_IO_MUX_SD_DATA3_U, -1, + PERIPHS_IO_MUX_MTDI_U, PERIPHS_IO_MUX_MTCK_U, PERIPHS_IO_MUX_MTMS_U, PERIPHS_IO_MUX_MTDO_U, + PAD_XPD_DCDC_CONF +}; + +uint8_t pin_func[GPIO_PIN_NUM] = { + FUNC_GPIO0, FUNC_GPIO1, FUNC_GPIO2, FUNC_GPIO3, + FUNC_GPIO4, FUNC_GPIO5, -1, -1, + -1, FUNC_GPIO9, FUNC_GPIO10, -1, + FUNC_GPIO12, FUNC_GPIO13, FUNC_GPIO14, FUNC_GPIO15, + -1 +}; + + +bool is_valid_gpio_pin(uint8 gpiopin) +{ + if(gpiopin >= GPIO_PIN_NUM) return false; + return (pin_func[gpiopin] != GPIO_PIN_FUNC_INVALID); +} diff --git a/modules/wifi.c b/modules/wifi.c new file mode 100644 index 0000000..f3165dc --- /dev/null +++ b/modules/wifi.c @@ -0,0 +1,97 @@ +/* + * wifi.c + * + * Created on: Dec 30, 2014 + * Author: Minh + */ +#include "wifi.h" +#include "user_interface.h" +#include "osapi.h" +#include "espconn.h" +#include "os_type.h" +#include "mem.h" +#include "debug.h" +#include "user_config.h" +#include "config.h" + +static ETSTimer WiFiLinker; +WifiCallback wifiCb = NULL; +static uint8_t wifiStatus = STATION_IDLE, lastWifiStatus = STATION_IDLE; + +static void ICACHE_FLASH_ATTR wifi_check_ip(void *arg) { + struct ip_info ipConfig; + + os_timer_disarm(&WiFiLinker); + wifi_get_ip_info(STATION_IF, &ipConfig); + wifiStatus = wifi_station_get_connect_status(); + if (wifiStatus == STATION_GOT_IP && ipConfig.ip.addr != 0) + { + + os_timer_setfn(&WiFiLinker, (os_timer_func_t *)wifi_check_ip, NULL); + os_timer_arm(&WiFiLinker, 2000, 0); + + + } + else + { + if(wifi_station_get_connect_status() == STATION_WRONG_PASSWORD) + { + + INFO("STATION_WRONG_PASSWORD\r\n"); + wifi_station_connect(); + + + } + else if(wifi_station_get_connect_status() == STATION_NO_AP_FOUND) + { + + INFO("STATION_NO_AP_FOUND\r\n"); + wifi_station_connect(); + + + } + else if(wifi_station_get_connect_status() == STATION_CONNECT_FAIL) + { + + INFO("STATION_CONNECT_FAIL\r\n"); + wifi_station_connect(); + + } + else + { + INFO("STATION_IDLE\r\n"); + } + + os_timer_setfn(&WiFiLinker, (os_timer_func_t *)wifi_check_ip, NULL); + os_timer_arm(&WiFiLinker, 500, 0); + } + if(wifiStatus != lastWifiStatus){ + lastWifiStatus = wifiStatus; + if(wifiCb) + wifiCb(wifiStatus); + } +} + +void ICACHE_FLASH_ATTR WIFI_Connect(const uint8_t* ssid, const uint8_t* pass, WifiCallback cb) { + struct station_config stationConf; + + INFO("WIFI_INIT\r\n"); + wifi_set_opmode(STATION_MODE); + wifi_station_set_auto_connect(FALSE); + wifiCb = cb; + + os_memset(&stationConf, 0, sizeof(struct station_config)); + + os_sprintf(stationConf.ssid, "%s", ssid); + os_sprintf(stationConf.password, "%s", pass); + + wifi_station_set_config(&stationConf); + + os_timer_disarm(&WiFiLinker); + os_timer_setfn(&WiFiLinker, (os_timer_func_t *)wifi_check_ip, NULL); + os_timer_arm(&WiFiLinker, 1000, 0); + + wifi_station_set_auto_connect(TRUE); + wifi_station_connect(); +} + diff --git a/twinkl b/twinkl new file mode 160000 index 0000000..2035657 --- /dev/null +++ b/twinkl @@ -0,0 +1 @@ +Subproject commit 2035657f8a34bc03433c1bf6135c1ac5016f866d diff --git a/user/Makefile b/user/Makefile new file mode 100644 index 0000000..dd3837c --- /dev/null +++ b/user/Makefile @@ -0,0 +1,44 @@ + +############################################################# +# Required variables for each makefile +# Discard this section from all parent makefiles +# Expected variables (with automatic defaults): +# CSRCS (all "C" files in the dir) +# SUBDIRS (all subdirs with a Makefile) +# GEN_LIBS - list of libs to be generated () +# GEN_IMAGES - list of images to be generated () +# COMPONENTS_xxx - a list of libs/objs in the form +# subdir/lib to be extracted and rolled up into +# a generated lib/image xxx.a () +# +ifndef PDIR +GEN_LIBS = libuser.a +endif + + +############################################################# +# Configuration i.e. compile options etc. +# Target specific stuff (defines etc.) goes in here! +# Generally values applying to a tree are captured in the +# makefile at its root level - these are then overridden +# for a subtree within the makefile rooted therein +# +#DEFINES += + +############################################################# +# Recursion Magic - Don't touch this!! +# +# Each subtree potentially has an include directory +# corresponding to the common APIs applicable to modules +# rooted at that subtree. Accordingly, the INCLUDE PATH +# of a module can only contain the include directories up +# its parent path, and not its siblings +# +# Required for each makefile to inherit from the parent +# + +INCLUDES := $(INCLUDES) -I $(PDIR)include +INCLUDES += -I ./ +PDIR := ../$(PDIR) +sinclude $(PDIR)Makefile + diff --git a/user/user_main.c b/user/user_main.c new file mode 100644 index 0000000..2d3b05d --- /dev/null +++ b/user/user_main.c @@ -0,0 +1,136 @@ +#include + +#include "ets_sys.h" +#include "ip_addr.h" +#include "espconn.h" +#include "osapi.h" +#include "wifi.h" +#include "gpio.h" +#include "mem.h" +#include "user_interface.h" + +#include "pin_map.h" +#include "debug.h" +#include "driver/uart.h" +#include "twinkl.h" + + +#define DMX_TASK_PRIO 0 +#define DMX_TASK_QUEUE_LENGTH 1 + + +struct espconn *udp_server; + +const int dmx_tx_pin = 2; + +volatile uint8_t update_scheduled = 0; +os_event_t dmx_task_queue[DMX_TASK_QUEUE_LENGTH]; +os_timer_t dmx_update_timer; + +uint8_t dmx_channels[TWINKL_CHANNEL_COUNT]; + + +void ICACHE_FLASH_ATTR udpserver_recv(void *arg, char *data, unsigned short len) +{ + INFO("Received %d bytes\n", len); + + if(len == sizeof(struct twinkl_message)) { + uint8_t changed_already; + + INFO("Data has the size of a twinkl message\n"); + twinkl_process_message((struct twinkl_message *) data); + INFO("Twinkl message has been processed\n"); + +/* if(!update_scheduled) { + update_scheduled = 1; + system_os_post(DMX_TASK_PRIO, 0, 0); + }*/ + } + +} + + +void ICACHE_FLASH_ATTR wifiConnectCb(uint8_t status) { + if(status == STATION_GOT_IP){ + INFO("Wifi connection established\n"); + udp_server = (struct espconn *) os_zalloc(sizeof(struct espconn)); + udp_server->type = ESPCONN_UDP; + udp_server->proto.udp = (esp_udp *) os_zalloc(sizeof(esp_udp)); + udp_server->proto.udp->local_port = udp_port; + espconn_regist_recvcb(udp_server, udpserver_recv); + + espconn_create(udp_server); + } + else if(udp_server != NULL) { + espconn_delete(udp_server); + os_free(udp_server); + udp_server = NULL; + } +} + + +void ICACHE_FLASH_ATTR dmx_task(os_event_t *events) { + int i; + update_scheduled = 0; + + if(twinkl_has_changes()) { + INFO("Updating DMX channels\n"); + twinkl_render(dmx_channels); + } + + //INFO("Sending DMX channels\n"); + + //ets_intr_lock(); + + //Space for break + PIN_FUNC_SELECT(pin_mux[dmx_tx_pin], FUNC_GPIO2); + gpio_output_set(0, BIT2, BIT2, 0); + os_delay_us(125); + + //Mark After Break + gpio_output_set(BIT2, 0, BIT2, 0); + os_delay_us(50); + + //Looks the wrong way round, but reduces jitter somehow + //Do not touch. + PIN_FUNC_SELECT(pin_mux[dmx_tx_pin], FUNC_U1TXD_BK); + uart_tx_one_char(1, 0); + //PIN_FUNC_SELECT(pin_mux[dmx_tx_pin], FUNC_U1TXD_BK); + + for(i = 0; i < TWINKL_CHANNEL_COUNT; i++) { + uart_tx_one_char(1, dmx_channels[i]); + } + + //ets_intr_unlock(); + + //INFO("Done sending DMX channels\n"); + os_timer_arm(&dmx_update_timer, 40, 0); +} + + +void dmx_update(void *arg) { + if(!update_scheduled) { + update_scheduled = 1; + system_os_post(DMX_TASK_PRIO, 0, 0); + } +} + +void user_init(void) { + uart_init(BIT_RATE_115200, BIT_RATE_250000); + os_delay_us(1000000); + + update_scheduled = 0; + memset(dmx_channels, 127, TWINKL_CHANNEL_COUNT); + + gpio_init(); + + twinkl_init(); + + os_timer_disarm(&dmx_update_timer); + os_timer_setfn(&dmx_update_timer, (os_timer_func_t *)dmx_update, NULL); + os_timer_arm(&dmx_update_timer, 40, 0); + + system_os_task(dmx_task, DMX_TASK_PRIO, dmx_task_queue, DMX_TASK_QUEUE_LENGTH); + + WIFI_Connect(wifi_ssid, wifi_password, wifiConnectCb); +}