Update ColorChord for the ESP8266

This commit is contained in:
cnlohr 2015-07-27 03:34:00 -04:00
parent ca4c90b1a8
commit 5a4c232d43
22 changed files with 1226 additions and 206 deletions

Binary file not shown.

Binary file not shown.

View file

@ -1,14 +1,17 @@
Portions of this code are under various Espressif licenses.
*Note if you use the ESP8266 port, you are bound to this license as well as
the regular ColorChord license.* (Yes, I'm aware one is a BSD-based license
and the other is a MIT-based license and will consider resolving this if
people want)
Please take not of the individual files. All files that are
written without license, by me are under the MIT license as reads below.
The MIT License (MIT)
ESPRSSIF MIT License
Copyright (c) 2014 Charles Lohr
Copyright (c) 2015 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
Portions Copyright (c) 2015 Charles Lohr
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only,
in which case, it is free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is

View file

@ -3,35 +3,35 @@ FW_FILE_1:=0x00000.bin
FW_FILE_2:=0x40000.bin
TARGET_OUT:=image.elf
OBJS:=driver/uart.o \
user/mystuff.o \
user/ws2812.o \
user/colorchord.o \
user/user_main.o
SRCS:=driver/uart.c \
user/mystuff.c \
user/ws2812.c \
user/colorchord.c \
user/ws2812_i2s.c \
user/hpatimer.c \
driver/adc.c \
../embeddedcommon/DFT32.c \
../embeddedcommon/embeddednf.c \
../embeddedcommon/embeddedout.c \
user/user_main.c
GCC_FOLDER:=~/esp8266/xtensa-toolchain-build/build-lx106
GCC_FOLDER:=~/esp8266/esp-open-sdk/xtensa-lx106-elf
ESPTOOL_PY:=~/esp8266/esptool/esptool.py
FW_TOOL:=~/esp8266/other/esptool/esptool
SDK:=/home/cnlohr/esp8266/esp_iot_sdk_v0.9.3
SDK:=/home/cnlohr/esp8266/esp_iot_sdk_v1.2.0
PORT:=/dev/ttyUSB0
#PORT:=/dev/ttyACM0
XTLIB:=$(SDK)/lib
XTGCCLIB:=$(GCC_FOLDER)/gcc-4.9.1-elf/xtensa-lx106-elf/libgcc/libgcc.a
FOLDERPREFIX:=$(GCC_FOLDER)/root/bin
XTGCCLIB:=$(GCC_FOLDER)/lib/gcc/xtensa-lx106-elf/4.8.2/libgcc.a
FOLDERPREFIX:=$(GCC_FOLDER)/bin
PREFIX:=$(FOLDERPREFIX)/xtensa-lx106-elf-
CC:=$(PREFIX)gcc
CFLAGS:=-mlongcalls -I$(SDK)/include -Imyclib -Iinclude -Iuser -Os -I$(SDK)/include/
CFLAGS:=-mlongcalls -I$(SDK)/include -Imyclib -Iinclude -Iuser -Os -I$(SDK)/include/ -I../embeddedcommon -Dmemcpy=ets_memcpy -Dmemset=ets_memset \
-DDFREQ=16000 -DCCEMBEDDED -DNUM_LIN_LEDS=24
#-DFREQ==12500 seems to work well.
# \
#
LDFLAGS_CORE:=\
-nostdlib \

View file

@ -1,5 +1,18 @@
#ESP8266 ColorChord Driver
#ESP8266 ColorChord
Please see the main ws2812esp8266 project for help with setting up your environment and programming, etc.
(based off of ESP8266 I2S WS2812 Driver)
This project is based off of the I2S interface for the mp3 player found here:
https://github.com/espressif/esp8266_mp3_decoder/
If you want more information about the build environment, etc. You should
check out the regular WS2812 driver, found here: https://github.com/cnlohr/ws2812esp8266
WARNING: This subproject is very jankey! It's about stable, but I don't think it's quite there yet.
## Hardware Connection
Unfortunately the I2S Out (WS2812 in) pin is the same as RX1 (pin 25), which means if you are programming via the UART, it'll need to be unplugged any time you're testing. The positive side of this is that it is a pin that is exposed on most ESP8266 breakout boards.
The audio data is taken from TOUT, but must be kept between 0 and 1V.

79
embedded8266/driver/adc.c Normal file
View file

@ -0,0 +1,79 @@
//I did not write this file, but I don't know where it came from.
#include "ets_sys.h"
#include "osapi.h"
#include "driver/adc.h"
#define i2c_bbpll 0x67
#define i2c_bbpll_en_audio_clock_out 4
#define i2c_bbpll_en_audio_clock_out_msb 7
#define i2c_bbpll_en_audio_clock_out_lsb 7
#define i2c_bbpll_hostid 4
#define i2c_saradc 0x6C
#define i2c_saradc_hostid 2
#define i2c_saradc_en_test 0
#define i2c_saradc_en_test_msb 5
#define i2c_saradc_en_test_lsb 5
#define i2c_writeReg_Mask(block, host_id, reg_add, Msb, Lsb, indata) \
rom_i2c_writeReg_Mask(block, host_id, reg_add, Msb, Lsb, indata)
#define i2c_readReg_Mask(block, host_id, reg_add, Msb, Lsb) \
rom_i2c_readReg_Mask_(block, host_id, reg_add, Msb, Lsb)
#define i2c_writeReg_Mask_def(block, reg_add, indata) \
i2c_writeReg_Mask(block, block##_hostid, reg_add, reg_add##_msb, reg_add##_lsb, indata)
#define i2c_readReg_Mask_def(block, reg_add) \
i2c_readReg_Mask(block, block##_hostid, reg_add, reg_add##_msb, reg_add##_lsb)
void ICACHE_FLASH_ATTR hs_adc_start(void)
{
i2c_writeReg_Mask_def(i2c_saradc, i2c_saradc_en_test, 1); //select test mux
//PWDET_CAL_EN=0, PKDET_CAL_EN=0
SET_PERI_REG_MASK(0x60000D5C, 0x200000);
while (GET_PERI_REG_BITS(0x60000D50, 26, 24) > 0); //wait r_state == 0
CLEAR_PERI_REG_MASK(0x60000D50, 0x02); //force_en=0
SET_PERI_REG_MASK(0x60000D50, 0x02); //force_en=1
}
uint16 hs_adc_read(void)
{
uint8 i;
uint16 sardata[8];
uint16_t sar_dout = 0;
while (GET_PERI_REG_BITS(0x60000D50, 26, 24) > 0); //wait r_state == 0
read_sar_dout(sardata);
for (i = 0; i < 8; i++) {
sar_dout += sardata[i];
}
#ifdef OLDWAY_NEEDS_RESTART
//tout = (sar_dout + 8) >> 4; //tout is 10 bits fraction
// ??? Why does this exist ??? It didn't start commented out, but now that I did comment it, it still seems happy.
// i2c_writeReg_Mask_def(i2c_saradc, i2c_saradc_en_test, 1); //select test mux
// while (GET_PERI_REG_BITS(0x60000D50, 26, 24) > 0); //wait r_state == 0
// CLEAR_PERI_REG_MASK(0x60000D5C, 0x200000);
// SET_PERI_REG_MASK(0x60000D60, 0x1); //force_en=1
// CLEAR_PERI_REG_MASK(0x60000D60, 0x1); //force_en=1
#else
//Start reading a new sample.
CLEAR_PERI_REG_MASK(0x60000D50, 0x02); //force_en=0
SET_PERI_REG_MASK(0x60000D50, 0x02); //force_en=1
#endif
return sar_dout; //tout is 10 bits fraction
}

View file

@ -169,52 +169,30 @@ uart0_sendStr(const char *str)
* Parameters : void *para - point to ETS_UART_INTR_ATTACH's arg
* Returns : NONE
*******************************************************************************/
extern void at_recvTask(void);
extern void charrx( uint8_t c );
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;
static uint8_t history[4];
static uint8_t hhead;
// 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();
uint8 uart_no = UART0;//UartDev.buff_uart_no;
volatile uint8_t v = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF;
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR);
}
// WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR);
history[hhead++] = v;
if( hhead > 3 ) hhead = 0;
// 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;
//Detect a request to reboot into bootloader.
if( history[hhead&3] == 0xc2 && history[(hhead+1)&3] == 0x42 && history[(hhead+2)&3] == 0x56 && history[(hhead+3)&3] == 0xff )
{
system_restart();
}
// system_os_post(at_recvTaskPrio, NULL, RcvChar);
charrx( v );
// //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 ;
// }
// }
}
/******************************************************************************
@ -242,6 +220,4 @@ 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();
}

BIN
embedded8266/image.elf Normal file → Executable file

Binary file not shown.

View file

@ -0,0 +1,6 @@
#ifndef __ADC_H__
#define __ADC_H__
void hs_adc_start(void);
uint16 hs_adc_read(void);
#endif

View file

@ -0,0 +1,139 @@
/*
* Copyright (c) Espressif System 2010 - 2012
*
*/
#ifndef _PIN_MUX_H_
#define _PIN_MUX_H_
#define PERIPHS_IO_MUX 0x60000800
#define PERIPHS_IO_MUX_FUNC 0x13
#define PERIPHS_IO_MUX_FUNC_S 4
#define PERIPHS_IO_MUX_PULLUP BIT7
#define PERIPHS_IO_MUX_PULLDWN BIT6
#define PERIPHS_IO_MUX_SLEEP_PULLUP BIT3
#define PERIPHS_IO_MUX_SLEEP_PULLDWN BIT2
#define PERIPHS_IO_MUX_SLEEP_OE BIT1
#define PERIPHS_IO_MUX_OE BIT0
#define PERIPHS_IO_MUX_CONF_U (PERIPHS_IO_MUX + 0x00)
#define SPI0_CLK_EQU_SYS_CLK BIT8
#define SPI1_CLK_EQU_SYS_CLK BIT9
#define PERIPHS_IO_MUX_MTDI_U (PERIPHS_IO_MUX + 0x04)
#define FUNC_MTDI 0
#define FUNC_I2SI_DATA 1
#define FUNC_HSPIQ_MISO 2
#define FUNC_GPIO12 3
#define FUNC_UART0_DTR 4
#define PERIPHS_IO_MUX_MTCK_U (PERIPHS_IO_MUX + 0x08)
#define FUNC_MTCK 0
#define FUNC_I2SI_BCK 1
#define FUNC_HSPID_MOSI 2
#define FUNC_GPIO13 3
#define FUNC_UART0_CTS 4
#define PERIPHS_IO_MUX_MTMS_U (PERIPHS_IO_MUX + 0x0C)
#define FUNC_MTMS 0
#define FUNC_I2SI_WS 1
#define FUNC_HSPI_CLK 2
#define FUNC_GPIO14 3
#define FUNC_UART0_DSR 4
#define PERIPHS_IO_MUX_MTDO_U (PERIPHS_IO_MUX + 0x10)
#define FUNC_MTDO 0
#define FUNC_I2SO_BCK 1
#define FUNC_HSPI_CS0 2
#define FUNC_GPIO15 3
#define FUNC_U0RTS 4
#define FUNC_UART0_RTS 4
#define PERIPHS_IO_MUX_U0RXD_U (PERIPHS_IO_MUX + 0x14)
#define FUNC_U0RXD 0
#define FUNC_I2SO_DATA 1
#define FUNC_GPIO3 3
#define FUNC_CLK_XTAL_BK 4
#define PERIPHS_IO_MUX_U0TXD_U (PERIPHS_IO_MUX + 0x18)
#define FUNC_U0TXD 0
#define FUNC_SPICS1 1
#define FUNC_GPIO1 3
#define FUNC_CLK_RTC_BK 4
#define PERIPHS_IO_MUX_SD_CLK_U (PERIPHS_IO_MUX + 0x1c)
#define FUNC_SDCLK 0
#define FUNC_SPICLK 1
#define FUNC_GPIO6 3
#define UART1_CTS 4
#define PERIPHS_IO_MUX_SD_DATA0_U (PERIPHS_IO_MUX + 0x20)
#define FUNC_SDDATA0 0
#define FUNC_SPIQ_MISO 1
#define FUNC_GPIO7 3
#define FUNC_U1TXD 4
#define FUNC_UART1_TXD 4
#define PERIPHS_IO_MUX_SD_DATA1_U (PERIPHS_IO_MUX + 0x24)
#define FUNC_SDDATA1 0
#define FUNC_SPID_MOSI 1
#define FUNC_GPIO8 3
#define FUNC_U1RXD 4
#define FUNC_UART1_RXD 4
#define PERIPHS_IO_MUX_SD_DATA2_U (PERIPHS_IO_MUX + 0x28)
#define FUNC_SDDATA2 0
#define FUNC_SPIHD 1
#define FUNC_GPIO9 3
#define UFNC_HSPIHD 4
#define PERIPHS_IO_MUX_SD_DATA3_U (PERIPHS_IO_MUX + 0x2c)
#define FUNC_SDDATA3 0
#define FUNC_SPIWP 1
#define FUNC_GPIO10 3
#define FUNC_HSPIWP 4
#define PERIPHS_IO_MUX_SD_CMD_U (PERIPHS_IO_MUX + 0x30)
#define FUNC_SDCMD 0
#define FUNC_SPICS0 1
#define FUNC_GPIO11 3
#define U1RTS 4
#define UART1_RTS 4
#define PERIPHS_IO_MUX_GPIO0_U (PERIPHS_IO_MUX + 0x34)
#define FUNC_GPIO0 0
#define FUNC_SPICS2 1
#define FUNC_CLK_OUT 4
#define PERIPHS_IO_MUX_GPIO2_U (PERIPHS_IO_MUX + 0x38)
#define FUNC_GPIO2 0
#define FUNC_I2SO_WS 1
#define FUNC_U1TXD_BK 2
#define FUNC_UART1_TXD_BK 2
#define FUNC_U0TXD_BK 4
#define FUNC_UART0_TXD_BK 4
#define PERIPHS_IO_MUX_GPIO4_U (PERIPHS_IO_MUX + 0x3C)
#define FUNC_GPIO4 0
#define FUNC_CLK_XTAL 1
#define PERIPHS_IO_MUX_GPIO5_U (PERIPHS_IO_MUX + 0x40)
#define FUNC_GPIO5 0
#define FUNC_CLK_RTC 1
#define PIN_PULLUP_DIS(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME, PERIPHS_IO_MUX_PULLUP)
#define PIN_PULLUP_EN(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME, PERIPHS_IO_MUX_PULLUP)
//XXX THIS LOOKS WRONG.
#undef PIN_FUNC_SELECT
#define PIN_FUNC_SELECT(PIN_NAME, FUNC) do { \
CLEAR_PERI_REG_MASK(PIN_NAME, (PERIPHS_IO_MUX_FUNC<<PERIPHS_IO_MUX_FUNC_S)); \
SET_PERI_REG_MASK(PIN_NAME, (((FUNC&BIT2)<<2)|(FUNC&0x3))<<PERIPHS_IO_MUX_FUNC_S); \
} while (0)
#endif //_PIN_MUX_H_

View file

@ -0,0 +1 @@
#include "c_types.h"

View file

@ -1,10 +1 @@
#ifndef __USER_CONFIG_H__
#define __USER_CONFIG_H__
#define USE_US_TIMER
#define USE_OPTIMIZE_PRINTF
#define ESP_PLATFORM 1
#endif

View file

@ -0,0 +1,58 @@
#include "hpatimer.h"
#include <driver/adc.h>
#include "osapi.h"
#include "mem.h"
#include "eagle_soc.h"
#include "user_interface.h"
#include "ets_sys.h"
//BUFFSIZE must be a power-of-two
volatile uint8_t sounddata[HPABUFFSIZE];
volatile uint16_t soundhead;
#define FRC1_ENABLE_TIMER BIT7
typedef enum {
DIVDED_BY_1 = 0,
DIVDED_BY_16 = 4,
DIVDED_BY_256 = 8,
} TIMER_PREDIVED_MODE;
typedef enum {
TM_LEVEL_INT = 1,
TM_EDGE_INT = 0,
} TIMER_INT_MODE;
#define FRC1_AUTO_RELOAD 64
static void timerhandle( void * v )
{
RTC_CLR_REG_MASK(FRC1_INT_ADDRESS, FRC1_INT_CLR_MASK);
uint16_t r = hs_adc_read();
sounddata[soundhead] = r>>6;
soundhead = (soundhead+1)&(HPABUFFSIZE-1);
}
void ICACHE_FLASH_ATTR StartHPATimer()
{
RTC_REG_WRITE(FRC1_CTRL_ADDRESS, FRC1_AUTO_RELOAD|
DIVDED_BY_16 | //5MHz main clock.
FRC1_ENABLE_TIMER |
TM_EDGE_INT );
RTC_REG_WRITE(FRC1_LOAD_ADDRESS, 5000000/DFREQ);
RTC_REG_WRITE(FRC1_COUNT_ADDRESS, 5000000/DFREQ);
//pwm_set_freq_duty(freq, duty);
//pwm_start();
// RTC_REG_WRITE(FRC1_LOAD_ADDRESS, local_single[0].h_time);
ETS_FRC_TIMER1_INTR_ATTACH(timerhandle, NULL);
TM1_EDGE_INT_ENABLE();
ETS_FRC1_INTR_ENABLE();
system_timer_reinit();
hs_adc_start();
}

View file

@ -0,0 +1,16 @@
#ifndef _HPATIMER_H
#define _HPATIMER_H
#include <c_types.h>
//Using a system timer on the ESP to poll the ADC in at a regular interval...
//BUFFSIZE must be a power-of-two
#define HPABUFFSIZE 512
extern volatile uint8_t sounddata[HPABUFFSIZE];
extern volatile uint16_t soundhead;
void StartHPATimer();
#endif

View file

@ -1,3 +1,18 @@
#include "mystuff.h"
char generic_print_buffer[384];
void user_rf_pre_init(void)
{
//nothing.
}
char * strcat( char * dest, char * src )
{
return strcat(dest, src );
}

View file

@ -3,6 +3,6 @@
extern char generic_print_buffer[384];
#define printf( ... ) os_sprintf( generic_print_buffer, __VA_ARGS__ ); uart0_sendStr( generic_print_buffer );
#define printf( ... ) ets_sprintf( generic_print_buffer, __VA_ARGS__ ); uart0_sendStr( generic_print_buffer );
#endif

View file

@ -0,0 +1,281 @@
//Generated at 2012-10-23 19:55:03
/*
* Copyright (c) 2010 - 2011 Espressif System
*
*/
#ifndef SLC_REGISTER_H_
#define SLC_REGISTER_H_
#define REG_SLC_BASE 0x60000B00
//version value:32'h091700
#define SLC_CONF0 (REG_SLC_BASE + 0x0)
#ifndef ESP_MAC_5
#define SLC_MODE 0x00000003
#define SLC_MODE_S 12
#endif
#define SLC_DATA_BURST_EN (BIT(9))
#define SLC_DSCR_BURST_EN (BIT(8))
#define SLC_RX_NO_RESTART_CLR (BIT(7))
#define SLC_RX_AUTO_WRBACK (BIT(6))
#define SLC_RX_LOOP_TEST (BIT(5))
#define SLC_TX_LOOP_TEST (BIT(4))
#define SLC_AHBM_RST (BIT(3))
#define SLC_AHBM_FIFO_RST (BIT(2))
#define SLC_RXLINK_RST (BIT(1))
#define SLC_TXLINK_RST (BIT(0))
#define SLC_INT_RAW (REG_SLC_BASE + 0x4)
#define SLC_TX_DSCR_EMPTY_INT_RAW (BIT(21))
#define SLC_RX_DSCR_ERR_INT_RAW (BIT(20))
#define SLC_TX_DSCR_ERR_INT_RAW (BIT(19))
#define SLC_TOHOST_INT_RAW (BIT(18))
#define SLC_RX_EOF_INT_RAW (BIT(17))
#define SLC_RX_DONE_INT_RAW (BIT(16))
#define SLC_TX_EOF_INT_RAW (BIT(15))
#define SLC_TX_DONE_INT_RAW (BIT(14))
#define SLC_TOKEN1_1TO0_INT_RAW (BIT(13))
#define SLC_TOKEN0_1TO0_INT_RAW (BIT(12))
#define SLC_TX_OVF_INT_RAW (BIT(11))
#define SLC_RX_UDF_INT_RAW (BIT(10))
#define SLC_TX_START_INT_RAW (BIT(9))
#define SLC_RX_START_INT_RAW (BIT(8))
#define SLC_FRHOST_BIT7_INT_RAW (BIT(7))
#define SLC_FRHOST_BIT6_INT_RAW (BIT(6))
#define SLC_FRHOST_BIT5_INT_RAW (BIT(5))
#define SLC_FRHOST_BIT4_INT_RAW (BIT(4))
#define SLC_FRHOST_BIT3_INT_RAW (BIT(3))
#define SLC_FRHOST_BIT2_INT_RAW (BIT(2))
#define SLC_FRHOST_BIT1_INT_RAW (BIT(1))
#define SLC_FRHOST_BIT0_INT_RAW (BIT(0))
#define SLC_INT_STATUS (REG_SLC_BASE + 0x8)
#define SLC_TX_DSCR_EMPTY_INT_ST (BIT(21))
#define SLC_RX_DSCR_ERR_INT_ST (BIT(20))
#define SLC_TX_DSCR_ERR_INT_ST (BIT(19))
#define SLC_TOHOST_INT_ST (BIT(18))
#define SLC_RX_EOF_INT_ST (BIT(17))
#define SLC_RX_DONE_INT_ST (BIT(16))
#define SLC_TX_EOF_INT_ST (BIT(15))
#define SLC_TX_DONE_INT_ST (BIT(14))
#define SLC_TOKEN1_1TO0_INT_ST (BIT(13))
#define SLC_TOKEN0_1TO0_INT_ST (BIT(12))
#define SLC_TX_OVF_INT_ST (BIT(11))
#define SLC_RX_UDF_INT_ST (BIT(10))
#define SLC_TX_START_INT_ST (BIT(9))
#define SLC_RX_START_INT_ST (BIT(8))
#define SLC_FRHOST_BIT7_INT_ST (BIT(7))
#define SLC_FRHOST_BIT6_INT_ST (BIT(6))
#define SLC_FRHOST_BIT5_INT_ST (BIT(5))
#define SLC_FRHOST_BIT4_INT_ST (BIT(4))
#define SLC_FRHOST_BIT3_INT_ST (BIT(3))
#define SLC_FRHOST_BIT2_INT_ST (BIT(2))
#define SLC_FRHOST_BIT1_INT_ST (BIT(1))
#define SLC_FRHOST_BIT0_INT_ST (BIT(0))
#define SLC_INT_ENA (REG_SLC_BASE + 0xC)
#define SLC_TX_DSCR_EMPTY_INT_ENA (BIT(21))
#define SLC_RX_DSCR_ERR_INT_ENA (BIT(20))
#define SLC_TX_DSCR_ERR_INT_ENA (BIT(19))
#define SLC_TOHOST_INT_ENA (BIT(18))
#define SLC_RX_EOF_INT_ENA (BIT(17))
#define SLC_RX_DONE_INT_ENA (BIT(16))
#define SLC_TX_EOF_INT_ENA (BIT(15))
#define SLC_TX_DONE_INT_ENA (BIT(14))
#define SLC_TOKEN1_1TO0_INT_ENA (BIT(13))
#define SLC_TOKEN0_1TO0_INT_ENA (BIT(12))
#define SLC_TX_OVF_INT_ENA (BIT(11))
#define SLC_RX_UDF_INT_ENA (BIT(10))
#define SLC_TX_START_INT_ENA (BIT(9))
#define SLC_RX_START_INT_ENA (BIT(8))
#define SLC_FRHOST_BIT7_INT_ENA (BIT(7))
#define SLC_FRHOST_BIT6_INT_ENA (BIT(6))
#define SLC_FRHOST_BIT5_INT_ENA (BIT(5))
#define SLC_FRHOST_BIT4_INT_ENA (BIT(4))
#define SLC_FRHOST_BIT3_INT_ENA (BIT(3))
#define SLC_FRHOST_BIT2_INT_ENA (BIT(2))
#define SLC_FRHOST_BIT1_INT_ENA (BIT(1))
#define SLC_FRHOST_BIT0_INT_ENA (BIT(0))
#define SLC_FRHOST_BIT_INT_ENA_ALL 0xff
#define SLC_INT_CLR (REG_SLC_BASE + 0x10)
#define SLC_TX_DSCR_EMPTY_INT_CLR (BIT(21))
#define SLC_RX_DSCR_ERR_INT_CLR (BIT(20))
#define SLC_TX_DSCR_ERR_INT_CLR (BIT(19))
#define SLC_TOHOST_INT_CLR (BIT(18))
#define SLC_RX_EOF_INT_CLR (BIT(17))
#define SLC_RX_DONE_INT_CLR (BIT(16))
#define SLC_TX_EOF_INT_CLR (BIT(15))
#define SLC_TX_DONE_INT_CLR (BIT(14))
#define SLC_TOKEN1_1TO0_INT_CLR (BIT(13))
#define SLC_TOKEN0_1TO0_INT_CLR (BIT(12))
#define SLC_TX_OVF_INT_CLR (BIT(11))
#define SLC_RX_UDF_INT_CLR (BIT(10))
#define SLC_TX_START_INT_CLR (BIT(9))
#define SLC_RX_START_INT_CLR (BIT(8))
#define SLC_FRHOST_BIT7_INT_CLR (BIT(7))
#define SLC_FRHOST_BIT6_INT_CLR (BIT(6))
#define SLC_FRHOST_BIT5_INT_CLR (BIT(5))
#define SLC_FRHOST_BIT4_INT_CLR (BIT(4))
#define SLC_FRHOST_BIT3_INT_CLR (BIT(3))
#define SLC_FRHOST_BIT2_INT_CLR (BIT(2))
#define SLC_FRHOST_BIT1_INT_CLR (BIT(1))
#define SLC_FRHOST_BIT0_INT_CLR (BIT(0))
#define SLC_RX_STATUS (REG_SLC_BASE + 0x14)
#define SLC_RX_EMPTY (BIT(1))
#define SLC_RX_FULL (BIT(0))
#define SLC_RX_FIFO_PUSH (REG_SLC_BASE + 0x18)
#define SLC_RXFIFO_PUSH (BIT(16))
#define SLC_RXFIFO_WDATA 0x000001FF
#define SLC_RXFIFO_WDATA_S 0
#define SLC_TX_STATUS (REG_SLC_BASE + 0x1C)
#define SLC_TX_EMPTY (BIT(1))
#define SLC_TX_FULL (BIT(0))
#define SLC_TX_FIFO_POP (REG_SLC_BASE + 0x20)
#define SLC_TXFIFO_POP (BIT(16))
#define SLC_TXFIFO_RDATA 0x000007FF
#define SLC_TXFIFO_RDATA_S 0
#define SLC_RX_LINK (REG_SLC_BASE + 0x24)
#define SLC_RXLINK_PARK (BIT(31))
#define SLC_RXLINK_RESTART (BIT(30))
#define SLC_RXLINK_START (BIT(29))
#define SLC_RXLINK_STOP (BIT(28))
#define SLC_RXLINK_DESCADDR_MASK 0x000FFFFF
#define SLC_RXLINK_ADDR_S 0
#define SLC_TX_LINK (REG_SLC_BASE + 0x28)
#define SLC_TXLINK_PARK (BIT(31))
#define SLC_TXLINK_RESTART (BIT(30))
#define SLC_TXLINK_START (BIT(29))
#define SLC_TXLINK_STOP (BIT(28))
#define SLC_TXLINK_DESCADDR_MASK 0x000FFFFF
#define SLC_TXLINK_ADDR_S 0
#define SLC_INTVEC_TOHOST (REG_SLC_BASE + 0x2C)
#define SLC_TOHOST_INTVEC 0x000000FF
#define SLC_TOHOST_INTVEC_S 0
#define SLC_TOKEN0 (REG_SLC_BASE + 0x30)
#define SLC_TOKEN0_MASK 0x00000FFF
#define SLC_TOKEN0_S 16
#define SLC_TOKEN0_LOCAL_INC_MORE (BIT(14))
#define SLC_TOKEN0_LOCAL_INC (BIT(13))
#define SLC_TOKEN0_LOCAL_WR (BIT(12))
#define SLC_TOKEN0_LOCAL_WDATA_MASK 0x00000FFF
#define SLC_TOKEN0_LOCAL_WDATA_S 0
#define SLC_TOKEN1 (REG_SLC_BASE + 0x34)
#define SLC_TOKEN1_MASK 0x00000FFF
#define SLC_TOKEN1_S 16
#define SLC_TOKEN1_LOCAL_INC_MORE (BIT(14))
#define SLC_TOKEN1_LOCAL_INC (BIT(13))
#define SLC_TOKEN1_LOCAL_WR (BIT(12))
#define SLC_TOKEN1_LOCAL_WDATA 0x00000FFF
#define SLC_TOKEN1_LOCAL_WDATA_S 0
#define SLC_CONF1 (REG_SLC_BASE + 0x38)
#define SLC_STATE0 (REG_SLC_BASE + 0x3C)
#define SLC_STATE1 (REG_SLC_BASE + 0x40)
#define SLC_BRIDGE_CONF (REG_SLC_BASE + 0x44)
#ifndef ESP_MAC_5
#define SLC_TX_PUSH_IDLE_NUM 0x0000FFFF
#define SLC_TX_PUSH_IDLE_NUM_S 16
#define SLC_TX_DUMMY_MODE (BIT(12))
#endif
#define SLC_FIFO_MAP_ENA 0x0000000F
#define SLC_FIFO_MAP_ENA_S 8
#define SLC_TXEOF_ENA 0x0000003F
#define SLC_TXEOF_ENA_S 0
#define SLC_RX_EOF_DES_ADDR (REG_SLC_BASE + 0x48)
#define SLC_TX_EOF_DES_ADDR (REG_SLC_BASE + 0x4C)
#define SLC_FROM_HOST_LAST_DESC SLC_TX_EOF_DES_ADDR
#define SLC_TO_HOST_LAST_DESC SLC_RX_EOF_DES_ADDR
#define SLC_RX_EOF_BFR_DES_ADDR (REG_SLC_BASE + 0x50)
#define SLC_AHB_TEST (REG_SLC_BASE + 0x54)
#define SLC_AHB_TESTADDR 0x00000003
#define SLC_AHB_TESTADDR_S 4
#define SLC_AHB_TESTMODE 0x00000007
#define SLC_AHB_TESTMODE_S 0
#define SLC_SDIO_ST (REG_SLC_BASE + 0x58)
#define SLC_BUS_ST 0x00000007
#define SLC_BUS_ST_S 12
#define SLC_SDIO_WAKEUP (BIT(8))
#define SLC_FUNC_ST 0x0000000F
#define SLC_FUNC_ST_S 4
#define SLC_CMD_ST 0x00000007
#define SLC_CMD_ST_S 0
#define SLC_RX_DSCR_CONF (REG_SLC_BASE + 0x5C)
#ifdef ESP_MAC_5
#define SLC_INFOR_NO_REPLACE (BIT(9))
#define SLC_TOKEN_NO_REPLACE (BIT(8))
#define SLC_POP_IDLE_CNT 0x000000FF
#else
#define SLC_RX_FILL_EN (BIT(20))
#define SLC_RX_EOF_MODE (BIT(19))
#define SLC_RX_FILL_MODE (BIT(18))
#define SLC_INFOR_NO_REPLACE (BIT(17))
#define SLC_TOKEN_NO_REPLACE (BIT(16))
#define SLC_POP_IDLE_CNT 0x0000FFFF
#endif
#define SLC_POP_IDLE_CNT_S 0
#define SLC_TXLINK_DSCR (REG_SLC_BASE + 0x60)
#define SLC_TXLINK_DSCR_BF0 (REG_SLC_BASE + 0x64)
#define SLC_TXLINK_DSCR_BF1 (REG_SLC_BASE + 0x68)
#define SLC_RXLINK_DSCR (REG_SLC_BASE + 0x6C)
#define SLC_RXLINK_DSCR_BF0 (REG_SLC_BASE + 0x70)
#define SLC_RXLINK_DSCR_BF1 (REG_SLC_BASE + 0x74)
#define SLC_DATE (REG_SLC_BASE + 0x78)
#define SLC_ID (REG_SLC_BASE + 0x7C)
#define SLC_HOST_CONF_W0 (REG_SLC_BASE + 0x80 + 0x14)
#define SLC_HOST_CONF_W1 (REG_SLC_BASE + 0x80 + 0x18)
#define SLC_HOST_CONF_W2 (REG_SLC_BASE + 0x80 + 0x20)
#define SLC_HOST_CONF_W3 (REG_SLC_BASE + 0x80 + 0x24)
#define SLC_HOST_CONF_W4 (REG_SLC_BASE + 0x80 + 0x28)
#define SLC_HOST_INTR_ST (REG_SLC_BASE + 0x80 + 0x1c)
#define SLC_HOST_INTR_CLR (REG_SLC_BASE + 0x80 + 0x30)
#define SLC_HOST_INTR_SOF_BIT (BIT(12))
#define SLC_HOST_INTR_ENA (REG_SLC_BASE + 0x80 + 0x34)
#define SLC_RX_NEW_PACKET_INT_ENA (BIT23)
#define SLC_HOST_TOHOST_BIT0_INT_ENA (BIT0)
#define SLC_HOST_CONF_W5 (REG_SLC_BASE + 0x80 + 0x3C)
#define SLC_HOST_INTR_RAW (REG_SLC_BASE + 0x80 + 0x8)
#define SLC_HOST_INTR_ENA_BIT (BIT(23))
//[15:12]: 0x3ff9xxxx -- 0b01 from_host
// 0x3ffaxxxx -- 0b10 general
// 0x3ffbxxxx -- 0b11 to_host
#define SLC_DATA_ADDR_CLEAR_MASK (~(0xf<<12))
#define SLC_FROM_HOST_ADDR_MASK (0x1<<12)
#define SLC_TO_HOST_ADDR_MASK (0x3<<12)
#define SLC_SET_FROM_HOST_ADDR_MASK(v) do { \
(v) &= SLC_DATA_ADDR_CLEAR_MASK; \
(v) |= SLC_FROM_HOST_ADDR_MASK; \
} while(0);
#define SLC_SET_TO_HOST_ADDR_MASK(v) do { \
(v) &= SLC_DATA_ADDR_CLEAR_MASK; \
(v) |= SLC_TO_HOST_ADDR_MASK; \
} while(0);
#define SLC_TX_DESC_DEBUG_REG 0x3ff0002c //[15:0] set to 0xcccc
#endif // SLC_REGISTER_H_INCLUDED

View file

@ -6,69 +6,114 @@
#include "osapi.h"
#include "espconn.h"
#include "mystuff.h"
#include "ws2812.h"
#include "ws2812_i2s.h"
#include "hpatimer.h"
#include <DFT32.h>
#include <embeddednf.h>
#include <embeddedout.h>
#define PORT 7777
#define SERVER_TIMEOUT 1000
#define SERVER_TIMEOUT 1500
#define MAX_CONNS 5
#define MAX_FRAME 2000
#define procTaskPrio 0
#define procTaskQueueLen 1
static volatile os_timer_t some_timer;
static struct espconn *pUdpServer;
//Note to self. In future consider looking at this: http://pastebin.com/6eLxSrNz
#define HPABUFFSIZE 512
extern volatile uint8_t sounddata[HPABUFFSIZE];
extern volatile uint16_t soundhead;
uint16_t soundtail;
//Call this once we've stacked together one full colorchord frame.
static void NewFrame()
{
//uint8_t led_outs[NUM_LIN_LEDS*3];
int i;
HandleFrameInfo();
UpdateLinearLEDs();
//SendSPI2812( ledOut, NUM_LIN_LEDS );
ws2812_push( ledOut, NUM_LIN_LEDS * 3 );
}
os_event_t procTaskQueue[procTaskQueueLen];
static uint8_t printed_ip = 0;
uint32_t samp_iir = 0;
int wf = 0;
//Tasks that happen all the time.
os_event_t procTaskQueue[procTaskQueueLen];
static void ICACHE_FLASH_ATTR
procTask(os_event_t *events)
static void procTask(os_event_t *events)
{
system_os_post(procTaskPrio, 0, 0 );
// printf( "%d\n", sounddata[soundtail] );
while( soundtail != soundhead )
{
int16_t samp = sounddata[soundtail];
samp_iir = samp_iir - (samp_iir>>10) + samp;
PushSample32( (samp - (samp_iir>>10))*16 );
soundtail = (soundtail+1)&(HPABUFFSIZE-1);
wf++;
if( wf == 128 )
{
NewFrame();
wf = 0;
}
}
if( events->sig == 0 && events->par == 0 )
{
//Idle Event.
struct station_config wcfg;
char stret[256];
char *stt = &stret[0];
struct ip_info ipi;
int stat = wifi_station_get_connect_status();
// printf( "STAT: %d\n", stat );
if( stat == STATION_WRONG_PASSWORD || stat == STATION_NO_AP_FOUND || stat == STATION_CONNECT_FAIL )
{
wifi_set_opmode_current( 2 );
stt += ets_sprintf( stt, "Connection failed: %d\n", stat );
uart0_sendStr(stret);
}
if( stat == STATION_GOT_IP && !printed_ip )
{
wifi_station_get_config( &wcfg );
wifi_get_ip_info(0, &ipi);
stt += ets_sprintf( stt, "STAT: %d\n", stat );
stt += ets_sprintf( stt, "IP: %d.%d.%d.%d\n", (ipi.ip.addr>>0)&0xff,(ipi.ip.addr>>8)&0xff,(ipi.ip.addr>>16)&0xff,(ipi.ip.addr>>24)&0xff );
stt += ets_sprintf( stt, "NM: %d.%d.%d.%d\n", (ipi.netmask.addr>>0)&0xff,(ipi.netmask.addr>>8)&0xff,(ipi.netmask.addr>>16)&0xff,(ipi.netmask.addr>>24)&0xff );
stt += ets_sprintf( stt, "GW: %d.%d.%d.%d\n", (ipi.gw.addr>>0)&0xff,(ipi.gw.addr>>8)&0xff,(ipi.gw.addr>>16)&0xff,(ipi.gw.addr>>24)&0xff );
stt += ets_sprintf( stt, "WCFG: /%s/%s/\n", wcfg.ssid, wcfg.password );
uart0_sendStr(stret);
printed_ip = 1;
}
}
}
//Timer event.
static void ICACHE_FLASH_ATTR
myTimer(void *arg)
static void myTimer(void *arg)
{
int i;
uart0_sendStr(".");
SetupConstants();
#define GPIO_OUTPUT_SET(gpio_no, bit_value) \
gpio_output_set(bit_value<<gpio_no, ((~bit_value)&0x01)<<gpio_no, 1<<gpio_no,0)
GPIO_OUTPUT_SET(GPIO_ID_PIN(WSGPIO), 0);
WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 1 );
//XXX LOOK HERE!!!
//Right now, I am not actually using real data from the inputs, but rather doing this to test performance of my algorithm.
//The next step is to take real ADC inpts.
for( i = 0; i < 4000; i++ )
{
HandleProgressiveInt( 0xaa, 0xbb );
}
WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 0 );
// uart0_sendStr(".");
// printf( "%d/%d\n",soundtail,soundhead );
// printf( "%d/%d\n",soundtail,soundhead );
// uint8_t ledout[] = { 0x00, 0xff, 0xaa, 0x00, 0xff, 0xaa, };
// ws2812_push( ledout, 6 );
}
@ -76,20 +121,15 @@ static void ICACHE_FLASH_ATTR
static void ICACHE_FLASH_ATTR
udpserver_recv(void *arg, char *pusrdata, unsigned short len)
{
int i = 0;
struct espconn *pespconn = (struct espconn *)arg;
uint8_t buffer[MAX_FRAME];
// uint8_t buffer[MAX_FRAME];
//Make sure watchdog is disabled. WS2812's take a while and can mess it up.
ets_wdt_disable();
os_intr_lock();
WS2812OutBuffer( pusrdata, len );
os_intr_unlock();
ets_sprintf( buffer, "%d\r\n", len );
uart0_sendStr(buffer);
// uint8_t ledout[] = { 0x00, 0xff, 0xaa, 0x00, 0xff, 0xaa, };
uart0_sendStr("X");
// ws2812_push( pusrdata, len );
}
void ICACHE_FLASH_ATTR at_recvTask()
void ICACHE_FLASH_ATTR charrx( uint8_t c )
{
//Called from UART.
}
@ -102,8 +142,19 @@ void user_init(void)
uart0_sendStr("\r\nCustom Server\r\n");
wifi_set_opmode( 2 ); //We broadcast our ESSID, wait for peopel to join.
/*
struct station_config stationConf;
wifi_set_opmode( 1 ); //We broadcast our ESSID, wait for peopel to join.
os_memcpy(&stationConf.ssid, "xxx", ets_strlen( "xxx" ) + 1);
os_memcpy(&stationConf.password, "yyy", ets_strlen( "yyy" ) + 1);
wifi_set_opmode( 1 );
wifi_station_set_config(&stationConf);
wifi_station_connect();**/
pUdpServer = (struct espconn *)os_zalloc(sizeof(struct espconn));
ets_memset( pUdpServer, 0, sizeof( struct espconn ) );
espconn_create( pUdpServer );
@ -112,31 +163,27 @@ void user_init(void)
pUdpServer->proto.udp->local_port = 7777;
espconn_regist_recvcb(pUdpServer, udpserver_recv);
wifi_station_dhcpc_start();
/* wifi_station_dhcpc_start();
*/
if( espconn_create( pUdpServer ) )
{
while(1) { uart0_sendStr( "\r\nFAULT\r\n" ); }
}
//XXX TODO figure out how to safely re-allow this.
ets_wdt_disable();
char outbuffer[] = { 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,0xff,0xff, 0x00,0xff,0x00 };
WS2812OutBuffer( outbuffer, 1 ); //Initialize the output.
//Add a process
system_os_task(procTask, procTaskPrio, procTaskQueue, procTaskQueueLen);
uart0_sendStr("\r\nCustom Server\r\n");
WS2812OutBuffer( outbuffer, sizeof(outbuffer) );
//Timer example
os_timer_disarm(&some_timer);
os_timer_setfn(&some_timer, (os_timer_func_t *)myTimer, NULL);
os_timer_arm(&some_timer, 1000, 1);
os_timer_arm(&some_timer, 100, 1);
Init(); //Init colorchord
StartHPATimer(); //Init the high speed ADC timer.
ws2812_init();
system_os_post(procTaskPrio, 0, 0 );
}

View file

@ -1,61 +0,0 @@
#include "ws2812.h"
#include "ets_sys.h"
#include "mystuff.h"
#include "osapi.h"
#define GPIO_OUTPUT_SET(gpio_no, bit_value) \
gpio_output_set(bit_value<<gpio_no, ((~bit_value)&0x01)<<gpio_no, 1<<gpio_no,0)
//I just used a scope to figure out the right time periods.
void SEND_WS_0()
{
uint8_t time = 8;
WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 1 );
WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 1 );
while(time--)
{
WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 0 );
}
}
void SEND_WS_1()
{
uint8_t time = 9;
while(time--)
{
WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 1 );
}
time = 3;
while(time--)
{
WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 0 );
}
}
void WS2812OutBuffer( uint8_t * buffer, uint16_t length )
{
uint16_t i;
GPIO_OUTPUT_SET(GPIO_ID_PIN(WSGPIO), 0);
for( i = 0; i < length; i++ )
{
uint8_t byte = buffer[i];
if( byte & 0x80 ) SEND_WS_1(); else SEND_WS_0();
if( byte & 0x40 ) SEND_WS_1(); else SEND_WS_0();
if( byte & 0x20 ) SEND_WS_1(); else SEND_WS_0();
if( byte & 0x10 ) SEND_WS_1(); else SEND_WS_0();
if( byte & 0x08 ) SEND_WS_1(); else SEND_WS_0();
if( byte & 0x04 ) SEND_WS_1(); else SEND_WS_0();
if( byte & 0x02 ) SEND_WS_1(); else SEND_WS_0();
if( byte & 0x01 ) SEND_WS_1(); else SEND_WS_0();
}
//reset will happen when it's low long enough.
//(don't call this function twice within 10us)
}

View file

@ -1,16 +0,0 @@
#ifndef _WS2812_H
#define _WS2812_H
#define WSGPIO 0
#include "c_types.h"
#include "user_interface.h"
#include "ets_sys.h"
#include "gpio.h"
//You will have to os_intr_lock(); os_intr_unlock();
void WS2812OutBuffer( uint8_t * buffer, uint16_t length );
#endif

View file

@ -0,0 +1,452 @@
/******************************************************************************
* Copyright 2013-2015 Espressif Systems
*
* FileName: i2s_freertos.c
*
* Description: I2S output routines for a FreeRTOS system. Uses DMA and a queue
* to abstract away the nitty-gritty details.
*
* Modification history:
* 2015/06/01, v1.0 File created.
* 2015/07/23, Switch to making it a WS2812 output device.
*******************************************************************************
Notes:
This is pretty badly hacked together from the MP3 example.
I spent some time trying to strip it down to avoid a lot of the TX_ stuff.
That seems to work.
Major suggestions that I couldn't figure out:
* Use interrupts to disable DMA, so it isn't running nonstop.
* Use interrupts to flag when new data can be sent.
When I try using interrupts, it seems to work for a bit but things fall apart
rather quickly and the engine just refuses to send anymore until reboot.
The way it works right now is to keep the DMA running forever and just update
the data in the buffer so it continues sending the frame.
*******************************************************************************/
#include "slc_register.h"
#include "mystuff.h"
#include <c_types.h>
#include "ws2812_i2s.h"
#include "user_interface.h"
#include "pin_mux_register.h"
//Creates an I2S SR of 93,750 Hz, or 3 MHz Bitclock (.333us/sample)
// 12000000L/(div*bestbck*2)
//It is likely you could speed this up a little.
#define WS_I2S_BCK 16
#define WS_I2S_DIV 4
#ifndef i2c_bbpll
#define i2c_bbpll 0x67
#define i2c_bbpll_en_audio_clock_out 4
#define i2c_bbpll_en_audio_clock_out_msb 7
#define i2c_bbpll_en_audio_clock_out_lsb 7
#define i2c_bbpll_hostid 4
#define i2c_writeReg_Mask(block, host_id, reg_add, Msb, Lsb, indata) rom_i2c_writeReg_Mask(block, host_id, reg_add, Msb, Lsb, indata)
#define i2c_readReg_Mask(block, host_id, reg_add, Msb, Lsb) rom_i2c_readReg_Mask(block, host_id, reg_add, Msb, Lsb)
#define i2c_writeReg_Mask_def(block, reg_add, indata) \
i2c_writeReg_Mask(block, block##_hostid, reg_add, reg_add##_msb, reg_add##_lsb, indata)
#define i2c_readReg_Mask_def(block, reg_add) \
i2c_readReg_Mask(block, block##_hostid, reg_add, reg_add##_msb, reg_add##_lsb)
#endif
#ifndef ETS_SLC_INUM
#define ETS_SLC_INUM 1
#endif
//From i2s_reg.h
#define DR_REG_I2S_BASE (0x60000e00)
#define I2STXFIFO (DR_REG_I2S_BASE + 0x0000)
#define I2SRXFIFO (DR_REG_I2S_BASE + 0x0004)
#define I2SCONF (DR_REG_I2S_BASE + 0x0008)
#define I2S_BCK_DIV_NUM 0x0000003F
#define I2S_BCK_DIV_NUM_S 22
#define I2S_CLKM_DIV_NUM 0x0000003F
#define I2S_CLKM_DIV_NUM_S 16
#define I2S_BITS_MOD 0x0000000F
#define I2S_BITS_MOD_S 12
#define I2S_RECE_MSB_SHIFT (BIT(11))
#define I2S_TRANS_MSB_SHIFT (BIT(10))
#define I2S_I2S_RX_START (BIT(9))
#define I2S_I2S_TX_START (BIT(8))
#define I2S_MSB_RIGHT (BIT(7))
#define I2S_RIGHT_FIRST (BIT(6))
#define I2S_RECE_SLAVE_MOD (BIT(5))
#define I2S_TRANS_SLAVE_MOD (BIT(4))
#define I2S_I2S_RX_FIFO_RESET (BIT(3))
#define I2S_I2S_TX_FIFO_RESET (BIT(2))
#define I2S_I2S_RX_RESET (BIT(1))
#define I2S_I2S_TX_RESET (BIT(0))
#define I2S_I2S_RESET_MASK 0xf
#define I2SINT_RAW (DR_REG_I2S_BASE + 0x000c)
#define I2S_I2S_TX_REMPTY_INT_RAW (BIT(5))
#define I2S_I2S_TX_WFULL_INT_RAW (BIT(4))
#define I2S_I2S_RX_REMPTY_INT_RAW (BIT(3))
#define I2S_I2S_RX_WFULL_INT_RAW (BIT(2))
#define I2S_I2S_TX_PUT_DATA_INT_RAW (BIT(1))
#define I2S_I2S_RX_TAKE_DATA_INT_RAW (BIT(0))
#define I2SINT_ST (DR_REG_I2S_BASE + 0x0010)
#define I2S_I2S_TX_REMPTY_INT_ST (BIT(5))
#define I2S_I2S_TX_WFULL_INT_ST (BIT(4))
#define I2S_I2S_RX_REMPTY_INT_ST (BIT(3))
#define I2S_I2S_RX_WFULL_INT_ST (BIT(2))
#define I2S_I2S_TX_PUT_DATA_INT_ST (BIT(1))
#define I2S_I2S_RX_TAKE_DATA_INT_ST (BIT(0))
#define I2SINT_ENA (DR_REG_I2S_BASE + 0x0014)
#define I2S_I2S_TX_REMPTY_INT_ENA (BIT(5))
#define I2S_I2S_TX_WFULL_INT_ENA (BIT(4))
#define I2S_I2S_RX_REMPTY_INT_ENA (BIT(3))
#define I2S_I2S_RX_WFULL_INT_ENA (BIT(2))
#define I2S_I2S_TX_PUT_DATA_INT_ENA (BIT(1))
#define I2S_I2S_RX_TAKE_DATA_INT_ENA (BIT(0))
#define I2SINT_CLR (DR_REG_I2S_BASE + 0x0018)
#define I2S_I2S_TX_REMPTY_INT_CLR (BIT(5))
#define I2S_I2S_TX_WFULL_INT_CLR (BIT(4))
#define I2S_I2S_RX_REMPTY_INT_CLR (BIT(3))
#define I2S_I2S_RX_WFULL_INT_CLR (BIT(2))
#define I2S_I2S_PUT_DATA_INT_CLR (BIT(1))
#define I2S_I2S_TAKE_DATA_INT_CLR (BIT(0))
#define I2STIMING (DR_REG_I2S_BASE + 0x001c)
#define I2S_TRANS_BCK_IN_INV (BIT(22))
#define I2S_RECE_DSYNC_SW (BIT(21))
#define I2S_TRANS_DSYNC_SW (BIT(20))
#define I2S_RECE_BCK_OUT_DELAY 0x00000003
#define I2S_RECE_BCK_OUT_DELAY_S 18
#define I2S_RECE_WS_OUT_DELAY 0x00000003
#define I2S_RECE_WS_OUT_DELAY_S 16
#define I2S_TRANS_SD_OUT_DELAY 0x00000003
#define I2S_TRANS_SD_OUT_DELAY_S 14
#define I2S_TRANS_WS_OUT_DELAY 0x00000003
#define I2S_TRANS_WS_OUT_DELAY_S 12
#define I2S_TRANS_BCK_OUT_DELAY 0x00000003
#define I2S_TRANS_BCK_OUT_DELAY_S 10
#define I2S_RECE_SD_IN_DELAY 0x00000003
#define I2S_RECE_SD_IN_DELAY_S 8
#define I2S_RECE_WS_IN_DELAY 0x00000003
#define I2S_RECE_WS_IN_DELAY_S 6
#define I2S_RECE_BCK_IN_DELAY 0x00000003
#define I2S_RECE_BCK_IN_DELAY_S 4
#define I2S_TRANS_WS_IN_DELAY 0x00000003
#define I2S_TRANS_WS_IN_DELAY_S 2
#define I2S_TRANS_BCK_IN_DELAY 0x00000003
#define I2S_TRANS_BCK_IN_DELAY_S 0
#define I2S_FIFO_CONF (DR_REG_I2S_BASE + 0x0020)
#define I2S_I2S_RX_FIFO_MOD 0x00000007
#define I2S_I2S_RX_FIFO_MOD_S 16
#define I2S_I2S_TX_FIFO_MOD 0x00000007
#define I2S_I2S_TX_FIFO_MOD_S 13
#define I2S_I2S_DSCR_EN (BIT(12))
#define I2S_I2S_TX_DATA_NUM 0x0000003F
#define I2S_I2S_TX_DATA_NUM_S 6
#define I2S_I2S_RX_DATA_NUM 0x0000003F
#define I2S_I2S_RX_DATA_NUM_S 0
#define I2SRXEOF_NUM (DR_REG_I2S_BASE + 0x0024)
#define I2S_I2S_RX_EOF_NUM 0xFFFFFFFF
#define I2S_I2S_RX_EOF_NUM_S 0
#define I2SCONF_SIGLE_DATA (DR_REG_I2S_BASE + 0x0028)
#define I2S_I2S_SIGLE_DATA 0xFFFFFFFF
#define I2S_I2S_SIGLE_DATA_S 0
#define I2SCONF_CHAN (DR_REG_I2S_BASE + 0x002c)
#define I2S_RX_CHAN_MOD 0x00000003
#define I2S_RX_CHAN_MOD_S 3
#define I2S_TX_CHAN_MOD 0x00000007
#define I2S_TX_CHAN_MOD_S 0
//From sdio_slv.h
struct sdio_queue
{
uint32 blocksize:12;
uint32 datalen:12;
uint32 unused:5;
uint32 sub_sof:1;
uint32 eof:1;
uint32 owner:1;
uint32 buf_ptr;
uint32 next_link_ptr;
};
struct sdio_slave_status_element
{
uint32 wr_busy:1;
uint32 rd_empty :1;
uint32 comm_cnt :3;
uint32 intr_no :3;
uint32 rx_length:16;
uint32 res:8;
};
union sdio_slave_status
{
struct sdio_slave_status_element elm_value;
uint32 word_value;
};
#define RX_AVAILIBLE 2
#define TX_AVAILIBLE 1
#define INIT_STAGE 0
#define SDIO_QUEUE_LEN 8
#define MOSI 0
#define MISO 1
#define SDIO_DATA_ERROR 6
#define SLC_INTEREST_EVENT (SLC_TX_EOF_INT_ENA | SLC_RX_EOF_INT_ENA | SLC_RX_UDF_INT_ENA | SLC_TX_DSCR_ERR_INT_ENA)
#define TRIG_TOHOST_INT() SET_PERI_REG_MASK(SLC_INTVEC_TOHOST , BIT0);\
CLEAR_PERI_REG_MASK(SLC_INTVEC_TOHOST , BIT0)
///Rest of program...
//Pointer to the I2S DMA buffer data
//static unsigned int i2sBuf[I2SDMABUFCNT][I2SDMABUFLEN];
//I2S DMA buffer descriptors
//static struct sdio_queue i2sBufDesc[I2SDMABUFCNT];
static struct sdio_queue i2sBufDescOut;
static struct sdio_queue i2sBufDescZeroes;
static unsigned int i2sZeroes[32];
static unsigned int i2sBlock[WS_BLOCKSIZE/4];
//Queue which contains empty DMA buffers
//DMA underrun counter
#ifdef USE_2812_INTERRUPTS
volatile uint8_t ws2812_dma_complete;
//This routine is called as soon as the DMA routine has something to tell us. All we
//handle here is the RX_EOF_INT status, which indicate the DMA has sent a buffer whose
//descriptor has the 'EOF' field set to 1.
LOCAL void slc_isr(void) {
//clear all intr flags
// WRITE_PERI_REG(SLC_INT_CLR, 0xffffffff);//slc_intr_status);
// ws2812_dma_complete = 1;
//This is a little wacky. This function actually gets called twice.
//Once for the initial transfer, but by the time we tell it to stop
//The other zero transfer's already begun.
// SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_STOP);
}
#endif
//Initialize I2S subsystem for DMA circular buffer use
void ICACHE_FLASH_ATTR ws2812_init()
{
int x, y;
//Reset DMA
SET_PERI_REG_MASK(SLC_CONF0, SLC_RXLINK_RST);//|SLC_TXLINK_RST);
CLEAR_PERI_REG_MASK(SLC_CONF0, SLC_RXLINK_RST);//|SLC_TXLINK_RST);
//Clear DMA int flags
SET_PERI_REG_MASK(SLC_INT_CLR, 0xffffffff);
CLEAR_PERI_REG_MASK(SLC_INT_CLR, 0xffffffff);
//Enable and configure DMA
CLEAR_PERI_REG_MASK(SLC_CONF0, (SLC_MODE<<SLC_MODE_S));
SET_PERI_REG_MASK(SLC_CONF0,(1<<SLC_MODE_S));
SET_PERI_REG_MASK(SLC_RX_DSCR_CONF,SLC_INFOR_NO_REPLACE|SLC_TOKEN_NO_REPLACE);
CLEAR_PERI_REG_MASK(SLC_RX_DSCR_CONF, SLC_RX_FILL_EN|SLC_RX_EOF_MODE | SLC_RX_FILL_MODE);
i2sBufDescOut.owner = 1;
i2sBufDescOut.eof = 1;
i2sBufDescOut.sub_sof = 0;
i2sBufDescOut.datalen = WS_BLOCKSIZE; //Size (in bytes)
i2sBufDescOut.blocksize = WS_BLOCKSIZE; //Size (in bytes)
i2sBufDescOut.buf_ptr=(uint32_t)&i2sBlock[0];
i2sBufDescOut.unused=0;
i2sBufDescOut.next_link_ptr=(uint32_t)&i2sBufDescZeroes; //At the end, just redirect the DMA to the zero buffer.
i2sBufDescZeroes.owner = 1;
i2sBufDescZeroes.eof = 1;
i2sBufDescZeroes.sub_sof = 0;
i2sBufDescZeroes.datalen = 32;
i2sBufDescZeroes.blocksize = 32;
i2sBufDescZeroes.buf_ptr=(uint32_t)&i2sZeroes[0];
i2sBufDescZeroes.unused=0;
i2sBufDescZeroes.next_link_ptr=(uint32_t)&i2sBufDescOut;
for( x = 0; x < 32; x++ )
{
i2sZeroes[x] = 0x00;
}
for( x = 0; x < WS_BLOCKSIZE/4; x++ )
{
i2sBlock[x] = 0x00000000;//(x == 0 || x == 999)?0xaa:0x00;
/* uint16_t * tt = (uint16_t*)&i2sBlock[x];
(*(tt+0)) = 0xA0F0;
(*(tt+1)) = 0xC0E0;*/
}
// CLEAR_PERI_REG_MASK(SLC_TX_LINK,SLC_TXLINK_DESCADDR_MASK);
// SET_PERI_REG_MASK(SLC_TX_LINK, ((uint32)&i2sBufDescZeroes) & SLC_TXLINK_DESCADDR_MASK); //any random desc is OK, we don't use TX but it needs something valid
CLEAR_PERI_REG_MASK(SLC_RX_LINK,SLC_RXLINK_DESCADDR_MASK);
SET_PERI_REG_MASK(SLC_RX_LINK, ((uint32)&i2sBufDescOut) & SLC_RXLINK_DESCADDR_MASK);
#if USE_2812_INTERRUPTS
//Attach the DMA interrupt
ets_isr_attach(ETS_SLC_INUM, slc_isr);
//Enable DMA operation intr
WRITE_PERI_REG(SLC_INT_ENA, SLC_RX_EOF_INT_ENA);
//clear any interrupt flags that are set
WRITE_PERI_REG(SLC_INT_CLR, 0xffffffff);
///enable DMA intr in cpu
ets_isr_unmask(1<<ETS_SLC_INUM);
#endif
//Start transmission
// SET_PERI_REG_MASK(SLC_TX_LINK, SLC_TXLINK_START);
SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_START);
//----
//Init pins to i2s functions
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_I2SO_DATA);
// PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_I2SO_WS);
// PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_I2SO_BCK);
//Enable clock to i2s subsystem
i2c_writeReg_Mask_def(i2c_bbpll, i2c_bbpll_en_audio_clock_out, 1);
//Reset I2S subsystem
CLEAR_PERI_REG_MASK(I2SCONF,I2S_I2S_RESET_MASK);
SET_PERI_REG_MASK(I2SCONF,I2S_I2S_RESET_MASK);
CLEAR_PERI_REG_MASK(I2SCONF,I2S_I2S_RESET_MASK);
//Select 16bits per channel (FIFO_MOD=0), no DMA access (FIFO only)
CLEAR_PERI_REG_MASK(I2S_FIFO_CONF, I2S_I2S_DSCR_EN|(I2S_I2S_RX_FIFO_MOD<<I2S_I2S_RX_FIFO_MOD_S)|(I2S_I2S_TX_FIFO_MOD<<I2S_I2S_TX_FIFO_MOD_S));
//Enable DMA in i2s subsystem
SET_PERI_REG_MASK(I2S_FIFO_CONF, I2S_I2S_DSCR_EN);
//tx/rx binaureal
// CLEAR_PERI_REG_MASK(I2SCONF_CHAN, (I2S_TX_CHAN_MOD<<I2S_TX_CHAN_MOD_S)|(I2S_RX_CHAN_MOD<<I2S_RX_CHAN_MOD_S));
#if USE_2812_INTERRUPTS
//Clear int
SET_PERI_REG_MASK(I2SINT_CLR,
I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR);
CLEAR_PERI_REG_MASK(I2SINT_CLR,
I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR);
#endif
//trans master&rece slave,MSB shift,right_first,msb right
CLEAR_PERI_REG_MASK(I2SCONF, I2S_TRANS_SLAVE_MOD|
(I2S_BITS_MOD<<I2S_BITS_MOD_S)|
(I2S_BCK_DIV_NUM <<I2S_BCK_DIV_NUM_S)|
(I2S_CLKM_DIV_NUM<<I2S_CLKM_DIV_NUM_S));
SET_PERI_REG_MASK(I2SCONF, I2S_RIGHT_FIRST|I2S_MSB_RIGHT|I2S_RECE_SLAVE_MOD|
I2S_RECE_MSB_SHIFT|I2S_TRANS_MSB_SHIFT|
(((WS_I2S_BCK-1)&I2S_BCK_DIV_NUM )<<I2S_BCK_DIV_NUM_S)|
(((WS_I2S_DIV-1)&I2S_CLKM_DIV_NUM)<<I2S_CLKM_DIV_NUM_S));
//No idea if ints are needed...
//clear int
SET_PERI_REG_MASK(I2SINT_CLR, I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR);
CLEAR_PERI_REG_MASK(I2SINT_CLR, I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR);
//enable int
SET_PERI_REG_MASK(I2SINT_ENA, I2S_I2S_RX_REMPTY_INT_ENA|I2S_I2S_RX_TAKE_DATA_INT_ENA);
//Start transmission
SET_PERI_REG_MASK(I2SCONF,I2S_I2S_TX_START);
}
//Tricky, send out WS2812 bits with coded pulses, one nibble, then the other.
static const uint16_t bitpatterns[16] = {
0b1000100010001000, 0b1000100010001110, 0b1000100011101000, 0b1000100011101110,
0b1000111010001000, 0b1000111010001110, 0b1000111011101000, 0b1000111011101110,
0b1110100010001000, 0b1110100010001110, 0b1110100011101000, 0b1110100011101110,
0b1110111010001000, 0b1110111010001110, 0b1110111011101000, 0b1110111011101110,
};
void ws2812_push( uint8_t * buffer, uint16_t buffersize )
{
uint16_t * bufferpl = (uint16_t*)&i2sBlock[0];
uint16_t place;
// while( !ws2812_dma_complete );
if( buffersize * 4 > WS_BLOCKSIZE ) return;
for( place = 0; place < buffersize; place++ )
{
uint8_t btosend = buffer[place];
*(bufferpl++) = bitpatterns[(btosend&0x0f)];
*(bufferpl++) = bitpatterns[(btosend>>4)&0x0f];
}
#ifdef USE_2812_INTERRUPTS
uint16_t leftover = buffersize & 0x1f;
if( leftover ) leftover = 32 - leftover;
for( place = 0; place < leftover; place++ )
{
*(bufferpl++) = 0;
*(bufferpl++) = 0;
}
buffersize += leftover;
uint16_t sizeout_words = buffersize * 2;
i2sBufDescOut.owner = 1;
i2sBufDescOut.eof = 1;
i2sBufDescOut.sub_sof = 0;
i2sBufDescOut.datalen = sizeout_words*2; //Size (in bytes)
i2sBufDescOut.blocksize = sizeout_words*2; //Size (in bytes)
i2sBufDescOut.buf_ptr = (uint32_t)&i2sBlock[0];
i2sBufDescOut.unused = 0;
i2sBufDescOut.next_link_ptr=(uint32_t)&i2sBufDescZeroes; //At the end, just redirect the DMA to the zero buffer.
SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_STOP);
CLEAR_PERI_REG_MASK(SLC_RX_LINK,SLC_RXLINK_DESCADDR_MASK);
SET_PERI_REG_MASK(SLC_RX_LINK, ((uint32)&i2sBufDescOut) & SLC_RXLINK_DESCADDR_MASK);
SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_START);
#endif
}

View file

@ -0,0 +1,20 @@
#ifndef _I2S_TEST
#define _I2S_TEST
//Stuff that should be for the header:
#include <c_types.h>
//Parameters for the I2S DMA behaviour
//#define I2SDMABUFCNT (2) //Number of buffers in the I2S circular buffer
//#define I2SDMABUFLEN (32*2) //Length of one buffer, in 32-bit words.
//NOTE: Blocksize MUST be divisible by 4. Cannot exceed 4092
//Each LED takes up 12 block bytes.
#define WS_BLOCKSIZE 4000
void ICACHE_FLASH_ATTR ws2812_init();
void ws2812_push( uint8_t * buffer, uint16_t buffersize ); //Buffersize = Nr LEDs * 3
#endif