├── LICENSE ├── web ├── md5.c ├── md5.h ├── Makefile ├── mfsmaker.c ├── pushtodev.c ├── execute_reflash.c └── page │ ├── menuinterface.js │ ├── jquery-2.1.4.min.js.gz │ ├── index.html │ └── main.js ├── image.elf-0x00000.bin ├── image.elf-0x40000.bin ├── .gitmodules ├── wsend ├── Makefile ├── README.md └── wsend.c ├── user ├── pattern.h ├── vars.h ├── ws2812_i2s.h ├── custom_commands.c ├── user_main.c ├── pin_mux_register.h ├── pattern.c ├── slc_register.h └── ws2812_i2s.c ├── Makefile ├── user.cfg └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | esp82xx/LICENSE -------------------------------------------------------------------------------- /web/md5.c: -------------------------------------------------------------------------------- 1 | ../esp82xx/web/md5.c -------------------------------------------------------------------------------- /web/md5.h: -------------------------------------------------------------------------------- 1 | ../esp82xx/web/md5.h -------------------------------------------------------------------------------- /web/Makefile: -------------------------------------------------------------------------------- 1 | ../esp82xx/web/Makefile -------------------------------------------------------------------------------- /web/mfsmaker.c: -------------------------------------------------------------------------------- 1 | ../esp82xx/web/mfsmaker.c -------------------------------------------------------------------------------- /web/pushtodev.c: -------------------------------------------------------------------------------- 1 | ../esp82xx/web/pushtodev.c -------------------------------------------------------------------------------- /web/execute_reflash.c: -------------------------------------------------------------------------------- 1 | ../esp82xx/web/execute_reflash.c -------------------------------------------------------------------------------- /web/page/menuinterface.js: -------------------------------------------------------------------------------- 1 | ../../esp82xx/web/page/menuinterface.js -------------------------------------------------------------------------------- /web/page/jquery-2.1.4.min.js.gz: -------------------------------------------------------------------------------- 1 | ../../esp82xx/web/page/jquery-2.1.4.min.js.gz -------------------------------------------------------------------------------- /image.elf-0x00000.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnlohr/esp8266ws2812i2s/HEAD/image.elf-0x00000.bin -------------------------------------------------------------------------------- /image.elf-0x40000.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnlohr/esp8266ws2812i2s/HEAD/image.elf-0x40000.bin -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "esp82xx"] 2 | path = esp82xx 3 | url = https://github.com/cnlohr/esp82xx.git 4 | -------------------------------------------------------------------------------- /wsend/Makefile: -------------------------------------------------------------------------------- 1 | include ../user.cfg 2 | include ../esp82xx/common.mf 3 | 4 | CC = gcc 5 | CFLAGS= -std=gnu99 -Wall -Wextra -O2 -march=native $(OPTS) -DNO_CTYPES 6 | LOADLIBES = -lm 7 | 8 | wsend : wsend.o ../user/pattern.o 9 | 10 | clean : 11 | rm -rf wsend.o wsend *~ 12 | 13 | -------------------------------------------------------------------------------- /wsend/README.md: -------------------------------------------------------------------------------- 1 | # wsend 2 | 3 | Ws(s)end is a driver that runs on your PC's end of the esp8266ws2812i2s driver. 4 | It does not compile for the ESP8266. 5 | You can use this to send packets and interesting patterns to esp8266 via network, that then passes them on to WS2812's. 6 | 7 | -------------------------------------------------------------------------------- /user/pattern.h: -------------------------------------------------------------------------------- 1 | #ifndef _PATTERN_H 2 | #define _PATTERN_H 3 | 4 | enum patterns{ 5 | PTRN_CONST=0, 6 | PTRN_DEFAULT=254, 7 | PTRN_NONE=255 ///< Constant color 8 | }; ///< Special patterns for connected LEDs 9 | 10 | uint64_t HSVtoHEX( float hue, float sat, float value ); 11 | 12 | uint32_t hex_pattern( uint8_t pattern, uint16_t light, uint16_t lights, uint32_t frame, uint8_t clr[3] ); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include user.cfg 2 | -include esp82xx/common.mf 3 | -include esp82xx/main.mf 4 | 5 | SRCS += user/ws2812_i2s.c user/pattern.c 6 | 7 | % : 8 | $(warning This is the empty rule. Something went wrong.) 9 | @true 10 | 11 | ifndef TARGET 12 | $(info Modules were not checked out... use git clone --recursive in the future. Pulling now.) 13 | $(shell git submodule update --init --recursive) 14 | endif 15 | 16 | purge : clean 17 | @cd web && $(MAKE) $(MFLAGS) $(MAKEOVERRIDES) clean 18 | @cd wsend && $(MAKE) $(MFLAGS) $(MAKEOVERRIDES) clean 19 | $(RM) $(FW_FILE1) $(FW_FILE2) $(BIN_TARGET) 20 | -------------------------------------------------------------------------------- /user/vars.h: -------------------------------------------------------------------------------- 1 | #ifndef _VARS_H 2 | #define _VARS_H 3 | 4 | #include "commonservices.h" 5 | 6 | #define BUILD_BUG_ON(condition) extern int build_bug_on[!(condition)-1] 7 | 8 | typedef struct { 9 | uint8_t ptrn; ///< Pattern to display on connected leds 10 | uint16_t nled; ///< Number of connected LEDs 11 | uint8_t clr[3]; ///< Color data (used for PATTERN_CONST) 12 | // ... add more here ... 13 | } __attribute__((__packed__)) usr_conf_t; 14 | BUILD_BUG_ON(sizeof(usr_conf_t)>USERDATA_SIZE); // Produce invalid code if struct is too large ("best" way of size checking at compile time) 15 | 16 | extern usr_conf_t * UsrCfg; ///< User data preserved between esp boots 17 | 18 | extern uint32_t frame; ///< Temporal position in pattern period 19 | extern uint8_t last_leds[]; ///< Current LED color data 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /user/ws2812_i2s.h: -------------------------------------------------------------------------------- 1 | //Copyright 2015 <>< Charles Lohr, See LICENSE file. 2 | //WS2812 sender that abuses the I2S interface on the WS2812. 3 | 4 | #ifndef _WS2812I2S_TEST 5 | #define _WS2812I2S_TEST 6 | 7 | //Stuff that should be for the header: 8 | 9 | #include 10 | 11 | //Parameters for the I2S DMA behaviour 12 | //#define I2SDMABUFCNT (2) //Number of buffers in the I2S circular buffer 13 | //#define I2SDMABUFLEN (32*2) //Length of one buffer, in 32-bit words. 14 | 15 | //NOTE: Blocksize MUST be divisible by 4. Cannot exceed 4092 16 | //Each LED takes up 12 block bytes in WS2812_FOUR_SAMPLE 17 | //Or 9 block bytes in WS2812_THREE_SAMPLE 18 | #define WS_BLOCKSIZE 4000 19 | 20 | //You can either have 3 or 4 samples per bit for WS2812s. 21 | //3 sample can't go quite as fast as 4. 22 | //3 sample uses more processing when updating than 4. 23 | //4 takes up more RAM per LED than 3. 24 | //3 has slightly more restrictve timing requirements. 25 | //4 has more DMA load when running. 26 | #define WS2812_THREE_SAMPLE 27 | //#define WS2812_FOUR_SAMPLE 28 | 29 | // timing for SK6812 LEDs, always uses 4bit samples 30 | //#define SK6812 31 | 32 | void ICACHE_FLASH_ATTR ws2812_init(); 33 | void ICACHE_FLASH_ATTR ws2812_push( uint8_t * buffer, uint16_t buffersize ); //Buffersize = Nr LEDs * 3 34 | 35 | #endif 36 | 37 | -------------------------------------------------------------------------------- /user.cfg: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # User Options 3 | ############################################################################### 4 | 5 | CHIP = 8266 6 | IP = 192.168.4.1 # does not actually set the IP in firmware 7 | PORT = /dev/ttyUSB0 # could also be /dev/ttyACM0 8 | WEB_PORT = 80 9 | COM_PORT = 7777 10 | BACKEND_PORT = 7878 11 | PAGE_OFFSET = 65536 # 1048576 12 | 13 | #MUST BE 1.5.4 14 | #SDK = $(HOME)/esp8266/ESP8266_NONOS_SDK 15 | ESP_GCC_VERS = 4.8.5 16 | 17 | FWBURNFLAGS = -b 1000000 18 | 19 | OPTS += -DICACHE_FLASH 20 | OPTS += -DSK6812 21 | 22 | #OPTS += -DWS_SLEEP=14000 23 | #OPTS += -DVERIFY_FLASH_WRITE 24 | #OPTS += -DDEBUG 25 | #OPTS += -DFREQ=12500 26 | 27 | PAGE_TITLE = esp8266 ws2812 i2s controller 28 | PAGE_SCRIPTS = main.js 29 | PAGE_HEADING = $(PAGE_TITLE) 30 | PAGE_INFO =

Welcome to the esp8266ws2812i2s Web-based GUI.

This GUI uses WebSockets, and has only been tested under the newest (as of April, 2016) Chrome and Firefox browsers.

For more information about this project, visit it on github, here: https://github.com/cnlohr/esp8266ws2812i2s

If you want to send light to this device, send a UDP packet to port $(COM_PORT) to it. The first 3 bytes will be ignored, after that will be GRB values, one byte each, for each WS2812 you want to control

31 | -------------------------------------------------------------------------------- /user/custom_commands.c: -------------------------------------------------------------------------------- 1 | //Copyright 2015 <>< Charles Lohr, see LICENSE file. 2 | 3 | #include 4 | #include 5 | #include "ws2812_i2s.h" 6 | #include "vars.h" 7 | #include "pattern.h" 8 | 9 | int ICACHE_FLASH_ATTR CustomCommand(char * buffer, int retsize, char *pusrdata, unsigned short len) 10 | { 11 | char * buffend = buffer; 12 | 13 | switch( pusrdata[1] ) { 14 | case 'C': case 'c': { //Custom command test 15 | buffend += ets_sprintf( buffend, "CC" ); 16 | return buffend-buffer; 17 | } break; 18 | 19 | case 'l': case 'L': { //LEDs 20 | int i, it = 0; 21 | buffend += ets_sprintf( buffend, "CL:%d:", UsrCfg->nled ); 22 | uint16_t toledsvals = UsrCfg->nled*3; 23 | if( toledsvals > 600 ) toledsvals = 600; 24 | for( i = 0; i < toledsvals; i++ ) 25 | { 26 | uint8_t samp = last_leds[it++]; 27 | *(buffend++) = tohex1( samp>>4 ); 28 | *(buffend++) = tohex1( samp&0x0f ); 29 | } 30 | return buffend-buffer; 31 | } break; 32 | 33 | case 'T': case 't': { // set led-ranges over Web-UI 34 | #ifdef DEBUG 35 | printf("Color Data: "); 36 | int it; 37 | for(it=3; itnled = (len-1) / 3; 44 | UsrCfg->ptrn = PTRN_NONE; 45 | frame = 0; 46 | } break; 47 | 48 | 49 | case 'P': case 'p': { // set pattern to be repeated 50 | if( len<5 ) break; 51 | frame = 0; 52 | UsrCfg->ptrn = (uint8_t)pusrdata[2]; 53 | uint8_t c1 = (uint8_t)pusrdata[3]; 54 | uint8_t c2 = (uint8_t)pusrdata[4]; 55 | UsrCfg->nled = (uint16_t)(c1<<8) + (uint16_t)c2; 56 | if( len>7 ) ets_memcpy(UsrCfg->clr, (uint8_t*)(pusrdata+5), 3); 57 | debug( "len: %u; ptrn: %i, nled: %i, clr: %02x%02x%02x\n", len, UsrCfg->ptrn, UsrCfg->nled, (int)pusrdata[5], (int)pusrdata[6], (int)pusrdata[7] ); 58 | CSSettingsSave(); 59 | return buffend-buffer; 60 | } break; 61 | 62 | } 63 | return -1; 64 | } 65 | -------------------------------------------------------------------------------- /wsend/wsend.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "../user/pattern.h" 10 | 11 | #ifndef WS_SLEEP 12 | #define WS_SLEEP 14000 13 | #endif 14 | 15 | int sockfd; 16 | struct sockaddr_in servaddr; 17 | 18 | int main( int argc, char ** argv ) 19 | { 20 | int firstoverride = -1; 21 | uint16_t lights = 186; 22 | uint8_t pattern = 0; 23 | unsigned ws_sleep = WS_SLEEP; 24 | if( argc < 2 ) 25 | { 26 | fprintf( stderr, "Error: usage: %s ip [no. of light=186] [override 1st LED (i.e. white on some systems))=-1] [pattern=-1] [sleep seconds=%g]\n", argv[0], (double)ws_sleep ); 27 | return -1; 28 | } 29 | uint32_t frame = 0; 30 | sockfd=socket(AF_INET,SOCK_DGRAM,0); 31 | 32 | bzero(&servaddr,sizeof(servaddr)); 33 | servaddr.sin_family = AF_INET; 34 | servaddr.sin_addr.s_addr=inet_addr(argv[1]); 35 | servaddr.sin_port=htons(COM_PORT); 36 | 37 | if( argc >= 3 ) lights = atoi( argv[2] ); 38 | if( argc >= 4 ) firstoverride = atoi( argv[3] ); 39 | if( argc >= 5 ) pattern = atoi( argv[4] ); 40 | if( argc >= 6 ) ws_sleep = atoi( argv[5] ); 41 | 42 | printf( "Lights: %d\n", lights ); 43 | 44 | while(1) { 45 | uint8_t buffer[lights*3]; 46 | unsigned i; 47 | for( i = 0; i < lights; i++ ) { 48 | uint32_t hex = 0; 49 | 50 | hex = hex_pattern( pattern, i, lights, frame, NULL ); 51 | 52 | buffer[0+i*3] = (hex>>8); 53 | buffer[1+i*3] = (hex); 54 | buffer[2+i*3] = (hex>>16); 55 | 56 | } 57 | 58 | if( firstoverride >= 0 ) 59 | buffer[0] = firstoverride; 60 | 61 | #ifdef BEAT 62 | for( i = 0; i < 4;i ++ ) 63 | { 64 | uint32_t hex = ((-frame % 48)+48)*256/48;//((frame %48) == 0)?0xffffff:0x000000; 65 | hex |= hex<<8 | hex<<16; 66 | buffer[0+i*3] = (hex>>8); 67 | buffer[1+i*3] = (hex); 68 | buffer[2+i*3] = (hex>>16); 69 | } 70 | #endif 71 | 72 | sendto(sockfd,buffer,sizeof(buffer),0, 73 | (struct sockaddr *)&servaddr,sizeof(servaddr)); 74 | frame++; 75 | #ifdef DEBUG 76 | for(i=0; i{{PAGE_TITLE}} 2 | {{PAGE_SCRIPT}} 3 | 4 | 14 | 15 | 16 |

{{PAGE_HEADING}}


17 | 18 | 19 | 20 | 24 | 25 | 26 | 27 | 28 |

Copyright (C) 2015-2016 <>< Charles Lohr, See LICENSE file for more info.

29 |

github-logo{{PROJECT_NAME}} - {{VERSSTR}}

30 |
31 |
...
32 | 33 | 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ESP8266 I2S WS2812 Driver 2 | 3 | Provides more reliable WS2812 driving... And a nifty websockets-based interface for the ESP8266. 4 | If you want to watch a video about this project, click the video link below. 5 | 6 | *Note: Most of the functionality is imported from a submodule ([esp82xx](https://github.com/cnlohr/esp82xx)). The submodule is more regularly updated and most of the technical description and troubleshooting advice is located there. You might want to `cd esp82xx; git pull origin master;` to fix (or sometimes introduce new) errors. The dev branch of both esp9266ws2812i2 and esp82xx might even be more cutting etch.* 7 | 8 | [![Youtube: Using I2S on the ESP8266 to drive WS2812Bs](http://img.youtube.com/vi/6zqGwxqJQnw/0.jpg)](http://www.youtube.com/watch?v=6zqGwxqJQnw) 9 | 10 | This project is based off of the Espressif I2S interface for an [mp3 player](https://github.com/espressif/esp8266_mp3_decoder/) 11 | 12 | If you want more information about the build environment, etc. You should check out [esp82xx](https://github.com/cnlohr/esp82xx). 13 | 14 | This project is still jankey and needs some cleanup. 15 | The way it currently works is to continuously send WS2812 frames and when new data comes in on port 7777, it just updates the frames. 16 | 17 | I wanted to make it so it would stop doing all DMA proesses so it could save bus contention, 18 | but I couldn't figure out how to make that happen. 19 | If I tried disabling and re-enabling, 20 | it seems to have caused the DMA to just freak out and turn off until chip reboot. 21 | 22 | The WS2812 output is synthesized from the input buffer. 23 | Any time a 0 is to be transmitted, we need a .3us pulse high and .9us low. 24 | If a 1, then we send a .9us high with a .3us low. The way we do this is we look at nibbles, i.e.: 25 | 26 | 0101 would convert into: 27 | 1000 1110 1000 1110 < bitstream that actually gets shipped out. 28 | 29 | Unfortunately this does mean it takes up 4x the space in RAM to DMA the data... But, it is very fast and efficient. 30 | 31 | ## Hardware Connection 32 | 33 | Unfortunately the I2S Output 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. 34 | 35 | ## Memory layout: 36 | 37 | We use a bit of a modified take on the old memory layout since, while we support OTA upgrades, we do so in a different way than the normal way. Not that HTTP is limited on parts with <1M, and OTA flashing is not supported at all on parts with <512kB. 38 | 39 | | Address | Size | Name / Description | 40 | | ------- |:-----:| ----------------------------- | 41 | | 00000h | 64k | 0x00000.bin, IRAM Code | 42 | | 10000h | 172k | Normally unused, HTTP may be here if signature found. Only used if you have < 1M part. | 43 | | 3A000h | 16k | Device Configuration | 44 | | 3E000h | 8k | May be used by ESP SDK. | 45 | | 40000h | 240k | 0x40000.bin, Cached code. | 46 | | 7C000h | 8k | May be used by ESP SDK. | 47 | | 7E000h | 8k | May be WiFi configuration | 48 | | 80000h | 512k | Scratchpad (Temp only!) | 49 | | 100000h | 1M+ | HTTP data, 1M on W25Q16. HTTP Used here if signature found. | 50 | 51 | -------------------------------------------------------------------------------- /user/user_main.c: -------------------------------------------------------------------------------- 1 | //Copyright 2015 <>< Charles Lohr, see LICENSE file. 2 | 3 | #include "mem.h" 4 | #include "c_types.h" 5 | #include "user_interface.h" 6 | #include "ets_sys.h" 7 | #include "uart.h" 8 | #include "osapi.h" 9 | #include "espconn.h" 10 | #include "esp82xxutil.h" 11 | #include "ws2812_i2s.h" 12 | #include "commonservices.h" 13 | #include 14 | #include "vars.h" 15 | #include "pattern.h" 16 | 17 | #define procTaskPrio 0 18 | #define procTaskQueueLen 1 19 | 20 | static volatile os_timer_t some_timer; 21 | static volatile os_timer_t pattern_timer; 22 | static struct espconn *pUdpServer; 23 | usr_conf_t * UsrCfg = (usr_conf_t*)(SETTINGS.UserData); 24 | uint8_t last_leds[512*3] = {0}; 25 | uint32_t frame = 0; 26 | 27 | 28 | //int ICACHE_FLASH_ATTR StartMDNS(); 29 | 30 | 31 | void ICACHE_FLASH_ATTR user_rf_pre_init(void) {/*nothing.*/} 32 | 33 | 34 | //Tasks that happen all the time. 35 | os_event_t procTaskQueue[procTaskQueueLen]; 36 | static void ICACHE_FLASH_ATTR procTask(os_event_t *events) 37 | { 38 | CSTick( 0 ); 39 | system_os_post(procTaskPrio, 0, 0 ); 40 | } 41 | 42 | 43 | //Display pattern on connected LEDs 44 | static void ICACHE_FLASH_ATTR patternTimer(void *arg) 45 | { 46 | if(UsrCfg->ptrn == PTRN_NONE) return; 47 | 48 | if( UsrCfg->nled > 450 ) UsrCfg->nled = 450; 49 | int it; 50 | for(it=0; itnled; ++it) { 51 | uint32_t hex = hex_pattern( UsrCfg->ptrn, it, UsrCfg->nled, frame, UsrCfg->clr ); 52 | last_leds[3*it+0] = (hex>>8); 53 | last_leds[3*it+1] = (hex); 54 | last_leds[3*it+2] = (hex>>16); 55 | } 56 | frame++; 57 | debug("Frame: %i", (int)frame); 58 | ws2812_push( (char*)last_leds, 3*UsrCfg->nled); 59 | } 60 | 61 | 62 | //Timer event. 63 | static void ICACHE_FLASH_ATTR myTimer(void *arg) 64 | { 65 | CSTick( 1 ); 66 | } 67 | 68 | 69 | //Called when new packet comes in. 70 | static void ICACHE_FLASH_ATTR 71 | udpserver_recv(void *arg, char *pusrdata, unsigned short len) 72 | { 73 | UsrCfg->ptrn = PTRN_NONE; 74 | struct espconn *pespconn = (struct espconn *)arg; 75 | 76 | uart0_sendStr("X"); 77 | 78 | ws2812_push( pusrdata+3, len-3 ); 79 | 80 | len -= 3; 81 | if( len > sizeof(last_leds) + 3 ) 82 | len = sizeof(last_leds) + 3; 83 | ets_memcpy( last_leds, pusrdata+3, len ); 84 | UsrCfg->nled = len / 3; 85 | } 86 | 87 | 88 | void ICACHE_FLASH_ATTR charrx( uint8_t c ) {/*Called from UART.*/} 89 | 90 | void ICACHE_FLASH_ATTR umcall( void ); 91 | 92 | void user_init(void) 93 | { 94 | uart_init(BIT_RATE_115200, BIT_RATE_115200); 95 | 96 | uart0_sendStr("\r\nesp82XX Web-GUI\r\n" VERSSTR "\b"); 97 | 98 | umcall(); 99 | } 100 | 101 | void ICACHE_FLASH_ATTR umcall( void ) 102 | { 103 | //Uncomment this to force a system restore. 104 | // system_restore(); 105 | 106 | CSSettingsLoad( 0 ); 107 | CSPreInit(); 108 | 109 | pUdpServer = (struct espconn *)os_zalloc(sizeof(struct espconn)); 110 | ets_memset( pUdpServer, 0, sizeof( struct espconn ) ); 111 | espconn_create( pUdpServer ); 112 | pUdpServer->type = ESPCONN_UDP; 113 | pUdpServer->proto.udp = (esp_udp *)os_zalloc(sizeof(esp_udp)); 114 | pUdpServer->proto.udp->local_port = COM_PORT; 115 | espconn_regist_recvcb(pUdpServer, udpserver_recv); 116 | 117 | if( espconn_create( pUdpServer ) ) 118 | while(1) 119 | uart0_sendStr( "\r\nFAULT\r\n" ); 120 | 121 | CSInit(); 122 | 123 | SetServiceName( "ws2812" ); 124 | AddMDNSName( "esp82xx" ); 125 | AddMDNSName( "ws2812" ); 126 | AddMDNSService( "_http._tcp", "An ESP8266 Webserver", WEB_PORT ); 127 | AddMDNSService( "_ws2812._udp", "WS2812 Driver", COM_PORT ); 128 | AddMDNSService( "_esp82xx._udp", "ESP8266 Backend", BACKEND_PORT ); 129 | 130 | //Add a process 131 | system_os_task(procTask, procTaskPrio, procTaskQueue, procTaskQueueLen); 132 | 133 | //Timer example 134 | os_timer_disarm(&some_timer); 135 | os_timer_setfn(&some_timer, (os_timer_func_t *)myTimer, NULL); 136 | os_timer_arm(&some_timer, 100, 1); 137 | 138 | //Pattern Timer example 139 | os_timer_disarm(&pattern_timer); 140 | os_timer_setfn(&pattern_timer, (os_timer_func_t *)patternTimer, NULL); 141 | os_timer_arm(&pattern_timer, 20, 1); //~50 Hz 142 | 143 | ws2812_init(); 144 | 145 | printf( "Boot Ok.\n" ); 146 | 147 | // wifi_set_sleep_type(LIGHT_SLEEP_T); 148 | // wifi_fpm_set_sleep_type(LIGHT_SLEEP_T); 149 | 150 | system_os_post(procTaskPrio, 0, 0 ); 151 | } 152 | 153 | 154 | //There is no code in this project that will cause reboots if interrupts are disabled. 155 | void EnterCritical() {} 156 | void ExitCritical() {} 157 | 158 | 159 | -------------------------------------------------------------------------------- /user/pin_mux_register.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Espressif System 2010 - 2012 3 | * 4 | */ 5 | 6 | #ifndef _PIN_MUX_H_ 7 | #define _PIN_MUX_H_ 8 | 9 | #define PERIPHS_IO_MUX 0x60000800 10 | 11 | #define PERIPHS_IO_MUX_FUNC 0x13 12 | #define PERIPHS_IO_MUX_FUNC_S 4 13 | #define PERIPHS_IO_MUX_PULLUP BIT7 14 | #define PERIPHS_IO_MUX_PULLDWN BIT6 15 | #define PERIPHS_IO_MUX_SLEEP_PULLUP BIT3 16 | #define PERIPHS_IO_MUX_SLEEP_PULLDWN BIT2 17 | #define PERIPHS_IO_MUX_SLEEP_OE BIT1 18 | #define PERIPHS_IO_MUX_OE BIT0 19 | 20 | #define PERIPHS_IO_MUX_CONF_U (PERIPHS_IO_MUX + 0x00) 21 | #define SPI0_CLK_EQU_SYS_CLK BIT8 22 | #define SPI1_CLK_EQU_SYS_CLK BIT9 23 | 24 | #define PERIPHS_IO_MUX_MTDI_U (PERIPHS_IO_MUX + 0x04) 25 | #define FUNC_MTDI 0 26 | #define FUNC_I2SI_DATA 1 27 | #define FUNC_HSPIQ_MISO 2 28 | #define FUNC_GPIO12 3 29 | #define FUNC_UART0_DTR 4 30 | 31 | #define PERIPHS_IO_MUX_MTCK_U (PERIPHS_IO_MUX + 0x08) 32 | #define FUNC_MTCK 0 33 | #define FUNC_I2SI_BCK 1 34 | #define FUNC_HSPID_MOSI 2 35 | #define FUNC_GPIO13 3 36 | #define FUNC_UART0_CTS 4 37 | 38 | #define PERIPHS_IO_MUX_MTMS_U (PERIPHS_IO_MUX + 0x0C) 39 | #define FUNC_MTMS 0 40 | #define FUNC_I2SI_WS 1 41 | #define FUNC_HSPI_CLK 2 42 | #define FUNC_GPIO14 3 43 | #define FUNC_UART0_DSR 4 44 | 45 | #define PERIPHS_IO_MUX_MTDO_U (PERIPHS_IO_MUX + 0x10) 46 | #define FUNC_MTDO 0 47 | #define FUNC_I2SO_BCK 1 48 | #define FUNC_HSPI_CS0 2 49 | #define FUNC_GPIO15 3 50 | #define FUNC_U0RTS 4 51 | #define FUNC_UART0_RTS 4 52 | 53 | #define PERIPHS_IO_MUX_U0RXD_U (PERIPHS_IO_MUX + 0x14) 54 | #define FUNC_U0RXD 0 55 | #define FUNC_I2SO_DATA 1 56 | #define FUNC_GPIO3 3 57 | #define FUNC_CLK_XTAL_BK 4 58 | 59 | #define PERIPHS_IO_MUX_U0TXD_U (PERIPHS_IO_MUX + 0x18) 60 | #define FUNC_U0TXD 0 61 | #define FUNC_SPICS1 1 62 | #define FUNC_GPIO1 3 63 | #define FUNC_CLK_RTC_BK 4 64 | 65 | #define PERIPHS_IO_MUX_SD_CLK_U (PERIPHS_IO_MUX + 0x1c) 66 | #define FUNC_SDCLK 0 67 | #define FUNC_SPICLK 1 68 | #define FUNC_GPIO6 3 69 | #define UART1_CTS 4 70 | 71 | #define PERIPHS_IO_MUX_SD_DATA0_U (PERIPHS_IO_MUX + 0x20) 72 | #define FUNC_SDDATA0 0 73 | #define FUNC_SPIQ_MISO 1 74 | #define FUNC_GPIO7 3 75 | #define FUNC_U1TXD 4 76 | #define FUNC_UART1_TXD 4 77 | 78 | #define PERIPHS_IO_MUX_SD_DATA1_U (PERIPHS_IO_MUX + 0x24) 79 | #define FUNC_SDDATA1 0 80 | #define FUNC_SPID_MOSI 1 81 | #define FUNC_GPIO8 3 82 | #define FUNC_U1RXD 4 83 | #define FUNC_UART1_RXD 4 84 | 85 | #define PERIPHS_IO_MUX_SD_DATA2_U (PERIPHS_IO_MUX + 0x28) 86 | #define FUNC_SDDATA2 0 87 | #define FUNC_SPIHD 1 88 | #define FUNC_GPIO9 3 89 | #define UFNC_HSPIHD 4 90 | 91 | #define PERIPHS_IO_MUX_SD_DATA3_U (PERIPHS_IO_MUX + 0x2c) 92 | #define FUNC_SDDATA3 0 93 | #define FUNC_SPIWP 1 94 | #define FUNC_GPIO10 3 95 | #define FUNC_HSPIWP 4 96 | 97 | #define PERIPHS_IO_MUX_SD_CMD_U (PERIPHS_IO_MUX + 0x30) 98 | #define FUNC_SDCMD 0 99 | #define FUNC_SPICS0 1 100 | #define FUNC_GPIO11 3 101 | #define U1RTS 4 102 | #define UART1_RTS 4 103 | 104 | #define PERIPHS_IO_MUX_GPIO0_U (PERIPHS_IO_MUX + 0x34) 105 | #define FUNC_GPIO0 0 106 | #define FUNC_SPICS2 1 107 | #define FUNC_CLK_OUT 4 108 | 109 | #define PERIPHS_IO_MUX_GPIO2_U (PERIPHS_IO_MUX + 0x38) 110 | #define FUNC_GPIO2 0 111 | #define FUNC_I2SO_WS 1 112 | #define FUNC_U1TXD_BK 2 113 | #define FUNC_UART1_TXD_BK 2 114 | #define FUNC_U0TXD_BK 4 115 | #define FUNC_UART0_TXD_BK 4 116 | 117 | #define PERIPHS_IO_MUX_GPIO4_U (PERIPHS_IO_MUX + 0x3C) 118 | #define FUNC_GPIO4 0 119 | #define FUNC_CLK_XTAL 1 120 | 121 | #define PERIPHS_IO_MUX_GPIO5_U (PERIPHS_IO_MUX + 0x40) 122 | #define FUNC_GPIO5 0 123 | #define FUNC_CLK_RTC 1 124 | 125 | #define PIN_PULLUP_DIS(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME, PERIPHS_IO_MUX_PULLUP) 126 | #define PIN_PULLUP_EN(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME, PERIPHS_IO_MUX_PULLUP) 127 | 128 | //XXX THIS LOOKS WRONG. 129 | 130 | #undef PIN_FUNC_SELECT 131 | 132 | #define PIN_FUNC_SELECT(PIN_NAME, FUNC) do { \ 133 | CLEAR_PERI_REG_MASK(PIN_NAME, (PERIPHS_IO_MUX_FUNC< 3 | #endif 4 | #include "pattern.h" 5 | #include 6 | 7 | float my_fmod(float arg1, float arg2) { 8 | int full = (int)(arg1/arg2); 9 | return arg1 - full*arg2; 10 | } 11 | 12 | uint64_t HSVtoHEX( float hue, float sat, float value ) 13 | { 14 | 15 | float pr, pg, pb, avg; pr=pg=pb=avg=0; 16 | short ora, og, ob; ora=og=ob=0; 17 | 18 | float ro = my_fmod( hue * 6, 6. ); 19 | ro = my_fmod( ro + 6 + 1, 6 ); //Hue was 60* off... 20 | 21 | //yellow->red 22 | if ( ro < 1 ) { pr = 1; pg = 1. - ro; } 23 | else if( ro < 2 ) { pr = 1; pb = ro - 1.; } 24 | else if( ro < 3 ) { pr = 3. - ro; pb = 1; } 25 | else if( ro < 4 ) { pb = 1; pg = ro - 3; } 26 | else if( ro < 5 ) { pb = 5 - ro; pg = 1; } 27 | else { pg = 1; pr = ro - 5; } 28 | 29 | //Actually, above math is backwards, oops! 30 | pr *= value; pg *= value; pb *= value; 31 | avg += pr; avg += pg; avg += pb; 32 | 33 | pr = pr * sat + avg * (1.-sat); 34 | pg = pg * sat + avg * (1.-sat); 35 | pb = pb * sat + avg * (1.-sat); 36 | 37 | ora = pr*255; og = pb*255; ob = pg*255; 38 | 39 | if( ora < 0 ) ora = 0; if( ora > 255 ) ora = 255; 40 | if( og < 0 ) og = 0; if( og > 255 ) og = 255; 41 | if( ob < 0 ) ob = 0; if( ob > 255 ) ob = 255; 42 | 43 | return (ob<<16) | (og<<8) | ora; 44 | } 45 | 46 | 47 | const unsigned char rands[] = { 48 | 0x67, 0xc6, 0x69, 0x73, 0x51, 0xff, 0x4a, 0xec, 0x29, 0xcd, 0xba, 0xab, 0xf2, 0xfb, 0xe3, 0x46, 49 | 0x7c, 0xc2, 0x54, 0xf8, 0x1b, 0xe8, 0xe7, 0x8d, 0x76, 0x5a, 0x2e, 0x63, 0x33, 0x9f, 0xc9, 0x9a, 50 | 0x66, 0x32, 0x0d, 0xb7, 0x31, 0x58, 0xa3, 0x5a, 0x25, 0x5d, 0x05, 0x17, 0x58, 0xe9, 0x5e, 0xd4, 51 | 0xab, 0xb2, 0xcd, 0xc6, 0x9b, 0xb4, 0x54, 0x11, 0x0e, 0x82, 0x74, 0x41, 0x21, 0x3d, 0xdc, 0x87, 52 | 0x70, 0xe9, 0x3e, 0xa1, 0x41, 0xe1, 0xfc, 0x67, 0x3e, 0x01, 0x7e, 0x97, 0xea, 0xdc, 0x6b, 0x96, 53 | 0x8f, 0x38, 0x5c, 0x2a, 0xec, 0xb0, 0x3b, 0xfb, 0x32, 0xaf, 0x3c, 0x54, 0xec, 0x18, 0xdb, 0x5c, 54 | 0x02, 0x1a, 0xfe, 0x43, 0xfb, 0xfa, 0xaa, 0x3a, 0xfb, 0x29, 0xd1, 0xe6, 0x05, 0x3c, 0x7c, 0x94, 55 | 0x75, 0xd8, 0xbe, 0x61, 0x89, 0xf9, 0x5c, 0xbb, 0xa8, 0x99, 0x0f, 0x95, 0xb1, 0xeb, 0xf1, 0xb3, 56 | 0x05, 0xef, 0xf7, 0x00, 0xe9, 0xa1, 0x3a, 0xe5, 0xca, 0x0b, 0xcb, 0xd0, 0x48, 0x47, 0x64, 0xbd, 57 | 0x1f, 0x23, 0x1e, 0xa8, 0x1c, 0x7b, 0x64, 0xc5, 0x14, 0x73, 0x5a, 0xc5, 0x5e, 0x4b, 0x79, 0x63, 58 | 0x3b, 0x70, 0x64, 0x24, 0x11, 0x9e, 0x09, 0xdc, 0xaa, 0xd4, 0xac, 0xf2, 0x1b, 0x10, 0xaf, 0x3b, 59 | 0x33, 0xcd, 0xe3, 0x50, 0x48, 0x47, 0x15, 0x5c, 0xbb, 0x6f, 0x22, 0x19, 0xba, 0x9b, 0x7d, 0xf5, 60 | 0x0b, 0xe1, 0x1a, 0x1c, 0x7f, 0x23, 0xf8, 0x29, 0xf8, 0xa4, 0x1b, 0x13, 0xb5, 0xca, 0x4e, 0xe8, 61 | 0x98, 0x32, 0x38, 0xe0, 0x79, 0x4d, 0x3d, 0x34, 0xbc, 0x5f, 0x4e, 0x77, 0xfa, 0xcb, 0x6c, 0x05, 62 | 0xac, 0x86, 0x21, 0x2b, 0xaa, 0x1a, 0x55, 0xa2, 0xbe, 0x70, 0xb5, 0x73, 0x3b, 0x04, 0x5c, 0xd3, 63 | 0x36, 0x94, 0xb3, 0xaf, 0xe2, 0xf0, 0xe4, 0x9e, 0x4f, 0x32, 0x15, 0x49, 0xfd, 0x82, 0x4e, 0xa9, }; 64 | const unsigned char sintable[] = { 65 | 0x80, 0x83, 0x86, 0x89, 0x8c, 0x8f, 0x92, 0x95, 0x99, 0x9c, 0x9f, 0xa2, 0xa5, 0xa8, 0xab, 0xad, 66 | 0xb0, 0xb3, 0xb6, 0xb9, 0xbc, 0xbe, 0xc1, 0xc4, 0xc6, 0xc9, 0xcb, 0xce, 0xd0, 0xd3, 0xd5, 0xd7, 67 | 0xda, 0xdc, 0xde, 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xe9, 0xeb, 0xed, 0xee, 0xf0, 0xf1, 0xf3, 0xf4, 68 | 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfc, 0xfd, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 69 | 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfd, 0xfc, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 70 | 0xf5, 0xf4, 0xf3, 0xf1, 0xf0, 0xee, 0xed, 0xeb, 0xe9, 0xe8, 0xe6, 0xe4, 0xe2, 0xe0, 0xde, 0xdc, 71 | 0xda, 0xd7, 0xd5, 0xd3, 0xd0, 0xce, 0xcb, 0xc9, 0xc6, 0xc4, 0xc1, 0xbe, 0xbc, 0xb9, 0xb6, 0xb3, 72 | 0xb0, 0xad, 0xab, 0xa8, 0xa5, 0xa2, 0x9f, 0x9c, 0x99, 0x95, 0x92, 0x8f, 0x8c, 0x89, 0x86, 0x83, 73 | 0x80, 0x7d, 0x79, 0x76, 0x73, 0x70, 0x6d, 0x6a, 0x67, 0x64, 0x61, 0x5e, 0x5b, 0x58, 0x55, 0x52, 74 | 0x4f, 0x4c, 0x49, 0x47, 0x44, 0x41, 0x3e, 0x3c, 0x39, 0x36, 0x34, 0x31, 0x2f, 0x2d, 0x2a, 0x28, 75 | 0x26, 0x24, 0x21, 0x1f, 0x1d, 0x1b, 0x1a, 0x18, 0x16, 0x14, 0x13, 0x11, 0x10, 0x0e, 0x0d, 0x0b, 76 | 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x04, 0x03, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 77 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x03, 0x04, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 78 | 0x0a, 0x0b, 0x0d, 0x0e, 0x10, 0x11, 0x13, 0x14, 0x16, 0x18, 0x1a, 0x1b, 0x1d, 0x1f, 0x21, 0x24, 79 | 0x26, 0x28, 0x2a, 0x2d, 0x2f, 0x31, 0x34, 0x36, 0x39, 0x3c, 0x3e, 0x41, 0x44, 0x47, 0x49, 0x4c, 80 | 0x4f, 0x52, 0x55, 0x58, 0x5b, 0x5e, 0x61, 0x64, 0x67, 0x6a, 0x6d, 0x70, 0x73, 0x76, 0x79, 0x7d, }; 81 | 82 | short dtr[512]; 83 | int init_dtr = 0; 84 | 85 | unsigned char intsin( short s ) 86 | { 87 | return sintable[((unsigned short)s)>>8]; 88 | } 89 | 90 | uint32_t hex_pattern( uint8_t pattern, uint16_t light, uint16_t lights, uint32_t frame, uint8_t clr[3] ) { 91 | uint32_t hex = 0; //0xbbggrr 92 | int i; 93 | 94 | switch( pattern ) { 95 | //For button 96 | case PTRN_CONST: if( clr != NULL ) hex = clr[0] | clr[1]<<8 | clr[2]<<16; break; 97 | case 1: hex = (light == (frame % lights))?0xFFFFFF:0x000000; break; 98 | case 2: hex = HSVtoHEX( light*(1/12.) + frame*(1./48.), 1, 1.0 ); break; 99 | case 3: hex = ((int32_t)((frame+light)%lights)>(lights-2))?0xffffff:0; break; //The worm. 100 | case 4: hex = HSVtoHEX( light*.03 - frame*.04, 1, (((((-light<<3)%256) - ((frame<<3)%256)+256)%256) ) /256.0*0.9-0.1); break; //Long, smooth, transitioning. 1.0 101 | 102 | //For wall art. 103 | case 5: hex = (((frame+light)%186)>160)?0xff8f8f:0; break; //The worm. 104 | case 6: hex = (((frame+light)%186)>130)?0x0000ff:0; break; //The red worm. 105 | case 7: hex = HSVtoHEX( light*.005 - frame*.001, 1, ((((-light%256) - ((frame>>1)%256)+256)%256) ) /256.0*1.2-0.1); break; 106 | case 8: hex = HSVtoHEX( light*.00500 + ((int)(frame*0.42))*.17, 1, 0.40 ); break;//Fiesta 107 | 108 | //and my favorite: 109 | case 9: hex = HSVtoHEX( light*.001 - frame*.001, 1, ((((light%256) - ((frame>>1)%256)+256)%256) ) /256.0*1.5-0.1); break; //Long, smooth, transitioning. 1.0 overloads. Trying 0.9. If 0.9 works, should back off. 110 | 111 | case 10: hex = HSVtoHEX( light*0.005376344 - frame*.001, 1.3, 1.0); break; //Long, smooth, transitioning. full-brigth 112 | 113 | //Chaser 114 | case 12: hex = HSVtoHEX( light*.002 + frame*.002, 4, 1.0 ); break; //0.50 = overload. 0.45 = overheat? =0.40 = HOT 115 | case 13: hex = HSVtoHEX( frame*.001, 1.0, 1.0); break; //Long, smooth, transitioning. full-brigth 116 | case 14: 117 | { 118 | float v1 = (((((light%256)<<2) - ((frame)%1024)+1024)%1024) ); 119 | float v2 = (((((light%256)<<2) - ((frame+1)%1024)+1024)%1024) ); 120 | float v3 = (((((light%256)<<2) - ((frame+2)%1024)+1024)%1024) ); 121 | float v4 = (((((light%256)<<2) - ((frame+3)%1024)+1024)%1024) ); 122 | hex = HSVtoHEX( light*.001 - frame*.001, 1, (v1+v2+v3+v4)/(4.0*1024.0)*1.2-0.1); 123 | break; //Long, smooth, transitioning. 1.0 overloads. Trying 0.9. If 0.9 works, should back off. 124 | } 125 | case 15: 126 | { 127 | int li = light/2; 128 | if( !init_dtr ) { for( i = 0; i < sizeof(dtr)/sizeof(dtr[0]); i++ ) dtr[i] = i*10; init_dtr = 1; } 129 | dtr[li] += rands[(li+(frame>>6))%(sizeof(rands)/sizeof(rands[0]))]; 130 | hex = (int)(((short)intsin( frame*2 + dtr[li]*4 ) ) * 1.0 ); 131 | if( hex > 0xff ) hex= 0xff; 132 | hex = (0xff<<16) | ((hex)) | (hex<<8); 133 | 134 | break; 135 | } 136 | case PTRN_NONE: break; 137 | default: hex = HSVtoHEX( light*.05 + frame*.01, 1, 1.0 ); 138 | } 139 | 140 | return hex; 141 | } 142 | -------------------------------------------------------------------------------- /web/page/main.js: -------------------------------------------------------------------------------- 1 | //Copyright (C) 2015 <>< Charles Lohr, see LICENSE file for more info. 2 | // 3 | //This particular file may be licensed under the MIT/x11, New BSD or ColorChord Licenses. 4 | 5 | function initLEDs() { 6 | var menItm = ` 7 | 8 |
9 | 10 |
11 | Select LEDs/Pattern:
12 | #LEDs: 13 | 14 |

15 | Patterns can include individual LEDs or ranges of LEDs separated by commata, e.g. "1-3,7,20-35". 16 | You can select colors via the color-picker or by holding Alt and clicking a color inside the color display. 17 | Alternatively, colors can be appended to a range, e.g. "1-3#ffff00". Rages without an appended color use the last specified one. 18 | Ranges can be entered by hand or selected in the color-display with the usual Shift+LeftClick and Alt+LeftClick combinations. 19 | If you set a pattern, use a low positive integer. 20 | "#LEDs" is the total number of LEDs connected to the esp8266 and must be provided.

21 |
22 | 23 | `; 24 | $('#MainMenu > tbody:last').after( menItm ); 25 | KickLEDs(); 26 | } 27 | 28 | is_leds_running = false; 29 | pause_led = false; 30 | led_data = []; 31 | nled = 4; 32 | 33 | 34 | function findPos(obj) { 35 | var curleft = 0, curtop = 0; 36 | if (obj.offsetParent) { 37 | do { 38 | curleft += obj.offsetLeft; 39 | curtop += obj.offsetTop; 40 | } while (obj = obj.offsetParent); 41 | return { x: curleft, y: curtop }; 42 | } 43 | return undefined; 44 | } 45 | 46 | 47 | function rgbToHex(r, g, b) { 48 | if (r > 255 || g > 255 || b > 255) 49 | throw "Invalid color component"; 50 | return ((r << 16) | (g << 8) | b).toString(16); 51 | } 52 | 53 | 54 | function strToByte(str, pos) { 55 | return parseInt(str.substr(pos, 2), 16); 56 | } 57 | 58 | 59 | function validateRange() { 60 | var obj = $('#LEDSelect'); 61 | var val = obj.val(); 62 | if( ! val.match(/^\d+(-\d+)?(#[a-zA-Z0-9]{6,6})?(,\d+(-\d+)?(#[a-zA-Z0-9]{6,6})?)*$/) ) { 63 | obj.css( "background-color", "#ff0000"); 64 | return false; 65 | } 66 | obj.css( "background-color", "#ffffff"); 67 | return val; 68 | } 69 | 70 | 71 | function SetPattern( ptrn ) { 72 | if( ! ptrn.match(/^\d+$/) ) { 73 | $('#LEDSelect').css( "background-color", "#ff0000"); 74 | return false; 75 | } 76 | var numLEDs = parseInt($('#LEDNum').val()); 77 | var color = document.getElementById('LEDColor').value; 78 | color = color.replace('#',''); 79 | $('#LEDSelect').css( "background-color", "#ffffff"); 80 | var qDat = new Uint8Array(ptrn==0 ? 8 : 5); 81 | var byte = 0; 82 | qDat[byte++] = "C".charCodeAt(); 83 | qDat[byte++] = "P".charCodeAt(); 84 | qDat[byte++] = parseInt(ptrn); 85 | qDat[byte++] = numLEDs>>8; 86 | qDat[byte++] = numLEDs%256; 87 | if( ptrn==0 ) { 88 | qDat[byte++] = strToByte(color, 0); 89 | qDat[byte++] = strToByte(color, 2); 90 | qDat[byte++] = strToByte(color, 4); 91 | } 92 | QueueOperation( qDat ); 93 | return true; 94 | } 95 | 96 | 97 | // Mostly setup stuff 98 | function KickLEDs() 99 | { 100 | // Validate Number of LEDS 101 | $('#LEDNum').change( function(e) { 102 | nled = parseInt( $('#LEDNum').val() ); 103 | if( val<0 || val>512 || isNaN(val) ) nled = 4; 104 | $('#LEDNum').val(nled); 105 | }); 106 | 107 | // Select a pattern to be used continously 108 | $('#LEDPbtn').click( function(e) { 109 | var ptrn = $('#LEDSelect').val(); 110 | return SetPattern( ptrn ); 111 | }); 112 | 113 | // Stop LEDs from changing 114 | $('#LEDSbtn').click( function(e) { 115 | return SetPattern( '255' ); 116 | }); 117 | 118 | // Turn all LEDs to black 119 | $('#LEDObtn').click( function(e) { 120 | document.getElementById('LEDColor').value = '#000000'; 121 | return SetPattern( '0' ); 122 | }); 123 | 124 | $('#LEDColor').change( function(e){ 125 | var sel = $('#LEDSelect'); 126 | val = sel.val(); 127 | sel.val( val.replace( /#[a-zA-Z0-9]{6,6}(?!.*#[a-zA-Z0-9]{6,6})/, this.value) ); 128 | //sel.val( val.replace( /#\d{6,6}$/, this.color) ); 129 | }); 130 | 131 | // Color Picker (from Canvas) 132 | //$('#LEDCanvas').mousemove(function(e) { 133 | $('#LEDCanvas').click( function(e) { 134 | var s = e.shiftKey, a = e.altKey, c = e.ctrlKey; 135 | var sel = $('#LEDSelect'); 136 | var pos = findPos(this); 137 | var ctx = this.getContext('2d'); 138 | var x = e.pageX-pos.x; 139 | var p = ctx.getImageData(x, e.pageY-pos.y, 1, 1).data; 140 | var n = parseInt(x * nled / this.clientWidth)+1; 141 | var clr = "#" + ("000000" + rgbToHex(p[0], p[1], p[2])).slice(-6) 142 | document.getElementById('LEDColor').value = clr; 143 | var val = validateRange(); 144 | //if( !val && !s ) return false; 145 | var ptrns = val.split(','); 146 | var endptrn = ptrns[ptrns.length-1] 147 | var endclr = endptrn.split('#'); 148 | endclr = endclr[1] ? endclr[1] : false; 149 | var singlet = endptrn.match(/^\d+$/); 150 | if( a ) { 151 | ; // Do nothing 152 | } else if( !s && !c ) { 153 | sel.val(n); 154 | } else if( s && !endclr ) { 155 | sel.val( val + '-' + n + clr ); 156 | } else if( c && !s && (endclr || singlet) ) { 157 | sel.val( (val ? val+',' : '') + n ); 158 | } 159 | validateRange(); 160 | }); 161 | 162 | // Set LED color via Button 163 | $('#LEDCbtn').click( function(e) { 164 | var val = validateRange(); 165 | if( !val ) return false; 166 | var numLEDs = parseInt( $('#LEDNum').val() ); 167 | var toks = val.split(','); 168 | var leds = new Array(); 169 | var color = document.getElementById('LEDColor').value; 170 | color = color.replace('#',''); 171 | for(var i=0; i 1 ) color = colsplt[1]; 175 | if( rangesplt.length < 2 ) { 176 | var idx = parseInt(rangesplt[0]); 177 | if(idx<=numLEDs) leds[idx] = color; 178 | } else { 179 | var min = parseInt(rangesplt[0]); 180 | var max = parseInt(rangesplt[1]); 181 | if( min > max ) { var tmp=min; min=max; max=tmp; } 182 | for(var j=min; j<=max && j<=numLEDs; ++j) 183 | leds[j] = color; 184 | } 185 | } 186 | 187 | var qDat = new Uint8Array(3*numLEDs+3); 188 | var byte = 0; 189 | qDat[byte++] = "C".charCodeAt(); 190 | qDat[byte++] = "T".charCodeAt(); 191 | qDat[byte++] = " ".charCodeAt(); 192 | for(var i=1; i<=numLEDs; ++i) { 193 | if( leds[i] && typeof(leds[i])!='undefined' ) { 194 | qDat[byte++] = strToByte(leds[i], 2); //String.fromCharCode(rVal); 195 | qDat[byte++] = strToByte(leds[i], 0); 196 | qDat[byte++] = strToByte(leds[i], 4); 197 | } else { 198 | var s = (i-1)*6; 199 | qDat[byte++] = strToByte(led_data, s+0); 200 | qDat[byte++] = strToByte(led_data, s+2); 201 | qDat[byte++] = strToByte(led_data, s+4); 202 | } 203 | } 204 | QueueOperation( qDat ); 205 | return true; 206 | }); 207 | 208 | $( "#LEDPauseButton" ).css( "background-color", (is_leds_running&&!pause_led)?"green":"red" ); 209 | 210 | if( !is_leds_running && !pause_led ) 211 | LEDDataTicker(); 212 | } 213 | 214 | 215 | window.addEventListener("load", initLEDs, false); 216 | 217 | 218 | function ToggleLEDPause() 219 | { 220 | pause_led = !pause_led; 221 | KickLEDs(); 222 | } 223 | 224 | 225 | // Update the display canvas 226 | function GotLED(req,data) 227 | { 228 | var ls = document.getElementById('LEDCanvasHolder'); 229 | var canvas = document.getElementById('LEDCanvas'); 230 | var ctx = canvas.getContext('2d'); 231 | if( canvas.width != ls.clientWidth-10 ) canvas.width = ls.clientWidth-10; 232 | if( ctx.canvas.width != canvas.clientWidth ) ctx.canvas.width = canvas.clientWidth; 233 | 234 | var secs = data.split( ":" ); 235 | 236 | $( "#LEDPauseButton" ).css( "background-color", "green" ); 237 | 238 | nled = Number( secs[1] ); 239 | led_data = secs[2]; 240 | ctx.clearRect( 0, 0, canvas.width, canvas.height ); 241 | 242 | for( var i = 0; i < nled; i++ ) { 243 | var x2 = i * canvas.clientWidth / nled; 244 | var samp = led_data.substr(i*6,6); 245 | 246 | ctx.fillStyle = "#" + samp.substr( 2, 2 ) + samp.substr( 0, 2 ) + samp.substr( 4, 2 ); 247 | ctx.lineWidth = 0; 248 | ctx.fillRect( x2, 0, canvas.clientWidth / nled+1, canvas.clientHeight ); 249 | } 250 | 251 | LEDDataTicker(); 252 | } 253 | 254 | 255 | function LEDDataTicker() 256 | { 257 | if( IsTabOpen('LEDs') && !pause_led ) { 258 | is_leds_running = true; 259 | QueueOperation( "CL", GotLED ); 260 | } else is_leds_running = 0; 261 | $( "#LEDPauseButton" ).css( "background-color", (is_leds_running&&!pause_led)?"green":"red" ); 262 | } 263 | -------------------------------------------------------------------------------- /user/slc_register.h: -------------------------------------------------------------------------------- 1 | //Generated at 2012-10-23 19:55:03 2 | /* 3 | * Copyright (c) 2010 - 2011 Espressif System 4 | * 5 | */ 6 | 7 | #ifndef SLC_REGISTER_H_ 8 | #define SLC_REGISTER_H_ 9 | 10 | #define REG_SLC_BASE 0x60000B00 11 | //version value:32'h091700 12 | 13 | #define SLC_CONF0 (REG_SLC_BASE + 0x0) 14 | #ifndef ESP_MAC_5 15 | #define SLC_MODE 0x00000003 16 | #define SLC_MODE_S 12 17 | #endif 18 | #define SLC_DATA_BURST_EN (BIT(9)) 19 | #define SLC_DSCR_BURST_EN (BIT(8)) 20 | #define SLC_RX_NO_RESTART_CLR (BIT(7)) 21 | #define SLC_RX_AUTO_WRBACK (BIT(6)) 22 | #define SLC_RX_LOOP_TEST (BIT(5)) 23 | #define SLC_TX_LOOP_TEST (BIT(4)) 24 | #define SLC_AHBM_RST (BIT(3)) 25 | #define SLC_AHBM_FIFO_RST (BIT(2)) 26 | #define SLC_RXLINK_RST (BIT(1)) 27 | #define SLC_TXLINK_RST (BIT(0)) 28 | 29 | #define SLC_INT_RAW (REG_SLC_BASE + 0x4) 30 | #define SLC_TX_DSCR_EMPTY_INT_RAW (BIT(21)) 31 | #define SLC_RX_DSCR_ERR_INT_RAW (BIT(20)) 32 | #define SLC_TX_DSCR_ERR_INT_RAW (BIT(19)) 33 | #define SLC_TOHOST_INT_RAW (BIT(18)) 34 | #define SLC_RX_EOF_INT_RAW (BIT(17)) 35 | #define SLC_RX_DONE_INT_RAW (BIT(16)) 36 | #define SLC_TX_EOF_INT_RAW (BIT(15)) 37 | #define SLC_TX_DONE_INT_RAW (BIT(14)) 38 | #define SLC_TOKEN1_1TO0_INT_RAW (BIT(13)) 39 | #define SLC_TOKEN0_1TO0_INT_RAW (BIT(12)) 40 | #define SLC_TX_OVF_INT_RAW (BIT(11)) 41 | #define SLC_RX_UDF_INT_RAW (BIT(10)) 42 | #define SLC_TX_START_INT_RAW (BIT(9)) 43 | #define SLC_RX_START_INT_RAW (BIT(8)) 44 | #define SLC_FRHOST_BIT7_INT_RAW (BIT(7)) 45 | #define SLC_FRHOST_BIT6_INT_RAW (BIT(6)) 46 | #define SLC_FRHOST_BIT5_INT_RAW (BIT(5)) 47 | #define SLC_FRHOST_BIT4_INT_RAW (BIT(4)) 48 | #define SLC_FRHOST_BIT3_INT_RAW (BIT(3)) 49 | #define SLC_FRHOST_BIT2_INT_RAW (BIT(2)) 50 | #define SLC_FRHOST_BIT1_INT_RAW (BIT(1)) 51 | #define SLC_FRHOST_BIT0_INT_RAW (BIT(0)) 52 | 53 | #define SLC_INT_STATUS (REG_SLC_BASE + 0x8) 54 | #define SLC_TX_DSCR_EMPTY_INT_ST (BIT(21)) 55 | #define SLC_RX_DSCR_ERR_INT_ST (BIT(20)) 56 | #define SLC_TX_DSCR_ERR_INT_ST (BIT(19)) 57 | #define SLC_TOHOST_INT_ST (BIT(18)) 58 | #define SLC_RX_EOF_INT_ST (BIT(17)) 59 | #define SLC_RX_DONE_INT_ST (BIT(16)) 60 | #define SLC_TX_EOF_INT_ST (BIT(15)) 61 | #define SLC_TX_DONE_INT_ST (BIT(14)) 62 | #define SLC_TOKEN1_1TO0_INT_ST (BIT(13)) 63 | #define SLC_TOKEN0_1TO0_INT_ST (BIT(12)) 64 | #define SLC_TX_OVF_INT_ST (BIT(11)) 65 | #define SLC_RX_UDF_INT_ST (BIT(10)) 66 | #define SLC_TX_START_INT_ST (BIT(9)) 67 | #define SLC_RX_START_INT_ST (BIT(8)) 68 | #define SLC_FRHOST_BIT7_INT_ST (BIT(7)) 69 | #define SLC_FRHOST_BIT6_INT_ST (BIT(6)) 70 | #define SLC_FRHOST_BIT5_INT_ST (BIT(5)) 71 | #define SLC_FRHOST_BIT4_INT_ST (BIT(4)) 72 | #define SLC_FRHOST_BIT3_INT_ST (BIT(3)) 73 | #define SLC_FRHOST_BIT2_INT_ST (BIT(2)) 74 | #define SLC_FRHOST_BIT1_INT_ST (BIT(1)) 75 | #define SLC_FRHOST_BIT0_INT_ST (BIT(0)) 76 | 77 | #define SLC_INT_ENA (REG_SLC_BASE + 0xC) 78 | #define SLC_TX_DSCR_EMPTY_INT_ENA (BIT(21)) 79 | #define SLC_RX_DSCR_ERR_INT_ENA (BIT(20)) 80 | #define SLC_TX_DSCR_ERR_INT_ENA (BIT(19)) 81 | #define SLC_TOHOST_INT_ENA (BIT(18)) 82 | #define SLC_RX_EOF_INT_ENA (BIT(17)) 83 | #define SLC_RX_DONE_INT_ENA (BIT(16)) 84 | #define SLC_TX_EOF_INT_ENA (BIT(15)) 85 | #define SLC_TX_DONE_INT_ENA (BIT(14)) 86 | #define SLC_TOKEN1_1TO0_INT_ENA (BIT(13)) 87 | #define SLC_TOKEN0_1TO0_INT_ENA (BIT(12)) 88 | #define SLC_TX_OVF_INT_ENA (BIT(11)) 89 | #define SLC_RX_UDF_INT_ENA (BIT(10)) 90 | #define SLC_TX_START_INT_ENA (BIT(9)) 91 | #define SLC_RX_START_INT_ENA (BIT(8)) 92 | #define SLC_FRHOST_BIT7_INT_ENA (BIT(7)) 93 | #define SLC_FRHOST_BIT6_INT_ENA (BIT(6)) 94 | #define SLC_FRHOST_BIT5_INT_ENA (BIT(5)) 95 | #define SLC_FRHOST_BIT4_INT_ENA (BIT(4)) 96 | #define SLC_FRHOST_BIT3_INT_ENA (BIT(3)) 97 | #define SLC_FRHOST_BIT2_INT_ENA (BIT(2)) 98 | #define SLC_FRHOST_BIT1_INT_ENA (BIT(1)) 99 | #define SLC_FRHOST_BIT0_INT_ENA (BIT(0)) 100 | 101 | #define SLC_FRHOST_BIT_INT_ENA_ALL 0xff 102 | 103 | #define SLC_INT_CLR (REG_SLC_BASE + 0x10) 104 | #define SLC_TX_DSCR_EMPTY_INT_CLR (BIT(21)) 105 | #define SLC_RX_DSCR_ERR_INT_CLR (BIT(20)) 106 | #define SLC_TX_DSCR_ERR_INT_CLR (BIT(19)) 107 | #define SLC_TOHOST_INT_CLR (BIT(18)) 108 | #define SLC_RX_EOF_INT_CLR (BIT(17)) 109 | #define SLC_RX_DONE_INT_CLR (BIT(16)) 110 | #define SLC_TX_EOF_INT_CLR (BIT(15)) 111 | #define SLC_TX_DONE_INT_CLR (BIT(14)) 112 | #define SLC_TOKEN1_1TO0_INT_CLR (BIT(13)) 113 | #define SLC_TOKEN0_1TO0_INT_CLR (BIT(12)) 114 | #define SLC_TX_OVF_INT_CLR (BIT(11)) 115 | #define SLC_RX_UDF_INT_CLR (BIT(10)) 116 | #define SLC_TX_START_INT_CLR (BIT(9)) 117 | #define SLC_RX_START_INT_CLR (BIT(8)) 118 | #define SLC_FRHOST_BIT7_INT_CLR (BIT(7)) 119 | #define SLC_FRHOST_BIT6_INT_CLR (BIT(6)) 120 | #define SLC_FRHOST_BIT5_INT_CLR (BIT(5)) 121 | #define SLC_FRHOST_BIT4_INT_CLR (BIT(4)) 122 | #define SLC_FRHOST_BIT3_INT_CLR (BIT(3)) 123 | #define SLC_FRHOST_BIT2_INT_CLR (BIT(2)) 124 | #define SLC_FRHOST_BIT1_INT_CLR (BIT(1)) 125 | #define SLC_FRHOST_BIT0_INT_CLR (BIT(0)) 126 | 127 | #define SLC_RX_STATUS (REG_SLC_BASE + 0x14) 128 | #define SLC_RX_EMPTY (BIT(1)) 129 | #define SLC_RX_FULL (BIT(0)) 130 | 131 | #define SLC_RX_FIFO_PUSH (REG_SLC_BASE + 0x18) 132 | #define SLC_RXFIFO_PUSH (BIT(16)) 133 | #define SLC_RXFIFO_WDATA 0x000001FF 134 | #define SLC_RXFIFO_WDATA_S 0 135 | 136 | #define SLC_TX_STATUS (REG_SLC_BASE + 0x1C) 137 | #define SLC_TX_EMPTY (BIT(1)) 138 | #define SLC_TX_FULL (BIT(0)) 139 | 140 | #define SLC_TX_FIFO_POP (REG_SLC_BASE + 0x20) 141 | #define SLC_TXFIFO_POP (BIT(16)) 142 | #define SLC_TXFIFO_RDATA 0x000007FF 143 | #define SLC_TXFIFO_RDATA_S 0 144 | 145 | #define SLC_RX_LINK (REG_SLC_BASE + 0x24) 146 | #define SLC_RXLINK_PARK (BIT(31)) 147 | #define SLC_RXLINK_RESTART (BIT(30)) 148 | #define SLC_RXLINK_START (BIT(29)) 149 | #define SLC_RXLINK_STOP (BIT(28)) 150 | #define SLC_RXLINK_DESCADDR_MASK 0x000FFFFF 151 | #define SLC_RXLINK_ADDR_S 0 152 | 153 | #define SLC_TX_LINK (REG_SLC_BASE + 0x28) 154 | #define SLC_TXLINK_PARK (BIT(31)) 155 | #define SLC_TXLINK_RESTART (BIT(30)) 156 | #define SLC_TXLINK_START (BIT(29)) 157 | #define SLC_TXLINK_STOP (BIT(28)) 158 | #define SLC_TXLINK_DESCADDR_MASK 0x000FFFFF 159 | #define SLC_TXLINK_ADDR_S 0 160 | 161 | #define SLC_INTVEC_TOHOST (REG_SLC_BASE + 0x2C) 162 | #define SLC_TOHOST_INTVEC 0x000000FF 163 | #define SLC_TOHOST_INTVEC_S 0 164 | 165 | #define SLC_TOKEN0 (REG_SLC_BASE + 0x30) 166 | #define SLC_TOKEN0_MASK 0x00000FFF 167 | #define SLC_TOKEN0_S 16 168 | #define SLC_TOKEN0_LOCAL_INC_MORE (BIT(14)) 169 | #define SLC_TOKEN0_LOCAL_INC (BIT(13)) 170 | #define SLC_TOKEN0_LOCAL_WR (BIT(12)) 171 | #define SLC_TOKEN0_LOCAL_WDATA_MASK 0x00000FFF 172 | #define SLC_TOKEN0_LOCAL_WDATA_S 0 173 | 174 | #define SLC_TOKEN1 (REG_SLC_BASE + 0x34) 175 | #define SLC_TOKEN1_MASK 0x00000FFF 176 | #define SLC_TOKEN1_S 16 177 | #define SLC_TOKEN1_LOCAL_INC_MORE (BIT(14)) 178 | #define SLC_TOKEN1_LOCAL_INC (BIT(13)) 179 | #define SLC_TOKEN1_LOCAL_WR (BIT(12)) 180 | #define SLC_TOKEN1_LOCAL_WDATA 0x00000FFF 181 | #define SLC_TOKEN1_LOCAL_WDATA_S 0 182 | 183 | #define SLC_CONF1 (REG_SLC_BASE + 0x38) 184 | #define SLC_STATE0 (REG_SLC_BASE + 0x3C) 185 | #define SLC_STATE1 (REG_SLC_BASE + 0x40) 186 | 187 | #define SLC_BRIDGE_CONF (REG_SLC_BASE + 0x44) 188 | #ifndef ESP_MAC_5 189 | #define SLC_TX_PUSH_IDLE_NUM 0x0000FFFF 190 | #define SLC_TX_PUSH_IDLE_NUM_S 16 191 | #define SLC_TX_DUMMY_MODE (BIT(12)) 192 | #endif 193 | #define SLC_FIFO_MAP_ENA 0x0000000F 194 | #define SLC_FIFO_MAP_ENA_S 8 195 | #define SLC_TXEOF_ENA 0x0000003F 196 | #define SLC_TXEOF_ENA_S 0 197 | 198 | #define SLC_RX_EOF_DES_ADDR (REG_SLC_BASE + 0x48) 199 | #define SLC_TX_EOF_DES_ADDR (REG_SLC_BASE + 0x4C) 200 | #define SLC_FROM_HOST_LAST_DESC SLC_TX_EOF_DES_ADDR 201 | #define SLC_TO_HOST_LAST_DESC SLC_RX_EOF_DES_ADDR 202 | 203 | #define SLC_RX_EOF_BFR_DES_ADDR (REG_SLC_BASE + 0x50) 204 | #define SLC_AHB_TEST (REG_SLC_BASE + 0x54) 205 | #define SLC_AHB_TESTADDR 0x00000003 206 | #define SLC_AHB_TESTADDR_S 4 207 | #define SLC_AHB_TESTMODE 0x00000007 208 | #define SLC_AHB_TESTMODE_S 0 209 | 210 | #define SLC_SDIO_ST (REG_SLC_BASE + 0x58) 211 | #define SLC_BUS_ST 0x00000007 212 | #define SLC_BUS_ST_S 12 213 | #define SLC_SDIO_WAKEUP (BIT(8)) 214 | #define SLC_FUNC_ST 0x0000000F 215 | #define SLC_FUNC_ST_S 4 216 | #define SLC_CMD_ST 0x00000007 217 | #define SLC_CMD_ST_S 0 218 | 219 | #define SLC_RX_DSCR_CONF (REG_SLC_BASE + 0x5C) 220 | #ifdef ESP_MAC_5 221 | #define SLC_INFOR_NO_REPLACE (BIT(9)) 222 | #define SLC_TOKEN_NO_REPLACE (BIT(8)) 223 | #define SLC_POP_IDLE_CNT 0x000000FF 224 | #else 225 | #define SLC_RX_FILL_EN (BIT(20)) 226 | #define SLC_RX_EOF_MODE (BIT(19)) 227 | #define SLC_RX_FILL_MODE (BIT(18)) 228 | #define SLC_INFOR_NO_REPLACE (BIT(17)) 229 | #define SLC_TOKEN_NO_REPLACE (BIT(16)) 230 | #define SLC_POP_IDLE_CNT 0x0000FFFF 231 | #endif 232 | #define SLC_POP_IDLE_CNT_S 0 233 | 234 | #define SLC_TXLINK_DSCR (REG_SLC_BASE + 0x60) 235 | #define SLC_TXLINK_DSCR_BF0 (REG_SLC_BASE + 0x64) 236 | #define SLC_TXLINK_DSCR_BF1 (REG_SLC_BASE + 0x68) 237 | #define SLC_RXLINK_DSCR (REG_SLC_BASE + 0x6C) 238 | #define SLC_RXLINK_DSCR_BF0 (REG_SLC_BASE + 0x70) 239 | #define SLC_RXLINK_DSCR_BF1 (REG_SLC_BASE + 0x74) 240 | #define SLC_DATE (REG_SLC_BASE + 0x78) 241 | #define SLC_ID (REG_SLC_BASE + 0x7C) 242 | 243 | #define SLC_HOST_CONF_W0 (REG_SLC_BASE + 0x80 + 0x14) 244 | #define SLC_HOST_CONF_W1 (REG_SLC_BASE + 0x80 + 0x18) 245 | #define SLC_HOST_CONF_W2 (REG_SLC_BASE + 0x80 + 0x20) 246 | #define SLC_HOST_CONF_W3 (REG_SLC_BASE + 0x80 + 0x24) 247 | #define SLC_HOST_CONF_W4 (REG_SLC_BASE + 0x80 + 0x28) 248 | 249 | #define SLC_HOST_INTR_ST (REG_SLC_BASE + 0x80 + 0x1c) 250 | #define SLC_HOST_INTR_CLR (REG_SLC_BASE + 0x80 + 0x30) 251 | #define SLC_HOST_INTR_SOF_BIT (BIT(12)) 252 | 253 | #define SLC_HOST_INTR_ENA (REG_SLC_BASE + 0x80 + 0x34) 254 | #define SLC_RX_NEW_PACKET_INT_ENA (BIT23) 255 | #define SLC_HOST_TOHOST_BIT0_INT_ENA (BIT0) 256 | #define SLC_HOST_CONF_W5 (REG_SLC_BASE + 0x80 + 0x3C) 257 | #define SLC_HOST_INTR_RAW (REG_SLC_BASE + 0x80 + 0x8) 258 | #define SLC_HOST_INTR_ENA_BIT (BIT(23)) 259 | //[15:12]: 0x3ff9xxxx -- 0b01 from_host 260 | // 0x3ffaxxxx -- 0b10 general 261 | // 0x3ffbxxxx -- 0b11 to_host 262 | #define SLC_DATA_ADDR_CLEAR_MASK (~(0xf<<12)) 263 | #define SLC_FROM_HOST_ADDR_MASK (0x1<<12) 264 | #define SLC_TO_HOST_ADDR_MASK (0x3<<12) 265 | 266 | #define SLC_SET_FROM_HOST_ADDR_MASK(v) do { \ 267 | (v) &= SLC_DATA_ADDR_CLEAR_MASK; \ 268 | (v) |= SLC_FROM_HOST_ADDR_MASK; \ 269 | } while(0); 270 | 271 | #define SLC_SET_TO_HOST_ADDR_MASK(v) do { \ 272 | (v) &= SLC_DATA_ADDR_CLEAR_MASK; \ 273 | (v) |= SLC_TO_HOST_ADDR_MASK; \ 274 | } while(0); 275 | 276 | 277 | #define SLC_TX_DESC_DEBUG_REG 0x3ff0002c //[15:0] set to 0xcccc 278 | 279 | 280 | #endif // SLC_REGISTER_H_INCLUDED 281 | 282 | -------------------------------------------------------------------------------- /user/ws2812_i2s.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Copyright 2013-2015 Espressif Systems 3 | * 2015 <>< Charles Lohr 4 | * 5 | * FileName: i2s_freertos.c 6 | * 7 | * Description: I2S output routines for a FreeRTOS system. Uses DMA and a queue 8 | * to abstract away the nitty-gritty details. 9 | * 10 | * Modification history: 11 | * 2015/06/01, v1.0 File created. 12 | * 2015/07/23, Switch to making it a WS2812 output device. 13 | ******************************************************************************* 14 | 15 | Notes: 16 | 17 | This is pretty badly hacked together from the MP3 example. 18 | I spent some time trying to strip it down to avoid a lot of the TX_ stuff. 19 | That seems to work. 20 | 21 | Major suggestions that I couldn't figure out: 22 | * Use interrupts to disable DMA, so it isn't running nonstop. 23 | * Use interrupts to flag when new data can be sent. 24 | 25 | When I try using interrupts, it seems to work for a bit but things fall apart 26 | rather quickly and the engine just refuses to send anymore until reboot. 27 | 28 | The way it works right now is to keep the DMA running forever and just update 29 | the data in the buffer so it continues sending the frame. 30 | 31 | Extra copyright info: 32 | Actually not much of this file is Copyright Espressif, comparativly little 33 | mostly just the stuff to make the I2S bus go. 34 | 35 | *******************************************************************************/ 36 | 37 | 38 | #include "slc_register.h" 39 | #include "esp82xxutil.h" 40 | #include 41 | #include "ws2812_i2s.h" 42 | #include "user_interface.h" 43 | #include "pin_mux_register.h" 44 | 45 | //Creates an I2S SR of 93,750 Hz, or 3 MHz Bitclock (.333us/sample) 46 | // 1600000000L/(div*bestbck) 47 | //It is likely you could speed this up a little. 48 | 49 | #ifdef WS2812_THREE_SAMPLE 50 | #define WS_I2S_BCK 21 //Seems to work as low as 18, but is shakey at 1. 51 | #define WS_I2S_DIV 3 52 | #elif defined( WS2812_FOUR_SAMPLE ) || defined(SK6812) 53 | #define WS_I2S_BCK 16 //Seems to work as low as 13, shoddy at 12. 54 | #define WS_I2S_DIV 3 55 | #else 56 | #error You need to either define WS2812_THREE_SAMPLE, WS2812_FOUR_SAMPLE or SK6812 57 | #endif 58 | 59 | #ifndef i2c_bbpll 60 | #define i2c_bbpll 0x67 61 | #define i2c_bbpll_en_audio_clock_out 4 62 | #define i2c_bbpll_en_audio_clock_out_msb 7 63 | #define i2c_bbpll_en_audio_clock_out_lsb 7 64 | #define i2c_bbpll_hostid 4 65 | 66 | #define i2c_writeReg_Mask(block, host_id, reg_add, Msb, Lsb, indata) rom_i2c_writeReg_Mask(block, host_id, reg_add, Msb, Lsb, indata) 67 | #define i2c_readReg_Mask(block, host_id, reg_add, Msb, Lsb) rom_i2c_readReg_Mask(block, host_id, reg_add, Msb, Lsb) 68 | #define i2c_writeReg_Mask_def(block, reg_add, indata) \ 69 | i2c_writeReg_Mask(block, block##_hostid, reg_add, reg_add##_msb, reg_add##_lsb, indata) 70 | #define i2c_readReg_Mask_def(block, reg_add) \ 71 | i2c_readReg_Mask(block, block##_hostid, reg_add, reg_add##_msb, reg_add##_lsb) 72 | #endif 73 | #ifndef ETS_SLC_INUM 74 | #define ETS_SLC_INUM 1 75 | #endif 76 | 77 | 78 | 79 | //From i2s_reg.h 80 | #define DR_REG_I2S_BASE (0x60000e00) 81 | 82 | #define I2STXFIFO (DR_REG_I2S_BASE + 0x0000) 83 | #define I2SRXFIFO (DR_REG_I2S_BASE + 0x0004) 84 | #define I2SCONF (DR_REG_I2S_BASE + 0x0008) 85 | #define I2S_BCK_DIV_NUM 0x0000003F 86 | #define I2S_BCK_DIV_NUM_S 22 87 | #define I2S_CLKM_DIV_NUM 0x0000003F 88 | #define I2S_CLKM_DIV_NUM_S 16 89 | #define I2S_BITS_MOD 0x0000000F 90 | #define I2S_BITS_MOD_S 12 91 | #define I2S_RECE_MSB_SHIFT (BIT(11)) 92 | #define I2S_TRANS_MSB_SHIFT (BIT(10)) 93 | #define I2S_I2S_RX_START (BIT(9)) 94 | #define I2S_I2S_TX_START (BIT(8)) 95 | #define I2S_MSB_RIGHT (BIT(7)) 96 | #define I2S_RIGHT_FIRST (BIT(6)) 97 | #define I2S_RECE_SLAVE_MOD (BIT(5)) 98 | #define I2S_TRANS_SLAVE_MOD (BIT(4)) 99 | #define I2S_I2S_RX_FIFO_RESET (BIT(3)) 100 | #define I2S_I2S_TX_FIFO_RESET (BIT(2)) 101 | #define I2S_I2S_RX_RESET (BIT(1)) 102 | #define I2S_I2S_TX_RESET (BIT(0)) 103 | #define I2S_I2S_RESET_MASK 0xf 104 | 105 | #define I2SINT_RAW (DR_REG_I2S_BASE + 0x000c) 106 | #define I2S_I2S_TX_REMPTY_INT_RAW (BIT(5)) 107 | #define I2S_I2S_TX_WFULL_INT_RAW (BIT(4)) 108 | #define I2S_I2S_RX_REMPTY_INT_RAW (BIT(3)) 109 | #define I2S_I2S_RX_WFULL_INT_RAW (BIT(2)) 110 | #define I2S_I2S_TX_PUT_DATA_INT_RAW (BIT(1)) 111 | #define I2S_I2S_RX_TAKE_DATA_INT_RAW (BIT(0)) 112 | 113 | 114 | #define I2SINT_ST (DR_REG_I2S_BASE + 0x0010) 115 | #define I2S_I2S_TX_REMPTY_INT_ST (BIT(5)) 116 | #define I2S_I2S_TX_WFULL_INT_ST (BIT(4)) 117 | #define I2S_I2S_RX_REMPTY_INT_ST (BIT(3)) 118 | #define I2S_I2S_RX_WFULL_INT_ST (BIT(2)) 119 | #define I2S_I2S_TX_PUT_DATA_INT_ST (BIT(1)) 120 | #define I2S_I2S_RX_TAKE_DATA_INT_ST (BIT(0)) 121 | 122 | #define I2SINT_ENA (DR_REG_I2S_BASE + 0x0014) 123 | #define I2S_I2S_TX_REMPTY_INT_ENA (BIT(5)) 124 | #define I2S_I2S_TX_WFULL_INT_ENA (BIT(4)) 125 | #define I2S_I2S_RX_REMPTY_INT_ENA (BIT(3)) 126 | #define I2S_I2S_RX_WFULL_INT_ENA (BIT(2)) 127 | #define I2S_I2S_TX_PUT_DATA_INT_ENA (BIT(1)) 128 | #define I2S_I2S_RX_TAKE_DATA_INT_ENA (BIT(0)) 129 | 130 | #define I2SINT_CLR (DR_REG_I2S_BASE + 0x0018) 131 | #define I2S_I2S_TX_REMPTY_INT_CLR (BIT(5)) 132 | #define I2S_I2S_TX_WFULL_INT_CLR (BIT(4)) 133 | #define I2S_I2S_RX_REMPTY_INT_CLR (BIT(3)) 134 | #define I2S_I2S_RX_WFULL_INT_CLR (BIT(2)) 135 | #define I2S_I2S_PUT_DATA_INT_CLR (BIT(1)) 136 | #define I2S_I2S_TAKE_DATA_INT_CLR (BIT(0)) 137 | 138 | #define I2STIMING (DR_REG_I2S_BASE + 0x001c) 139 | #define I2S_TRANS_BCK_IN_INV (BIT(22)) 140 | #define I2S_RECE_DSYNC_SW (BIT(21)) 141 | #define I2S_TRANS_DSYNC_SW (BIT(20)) 142 | #define I2S_RECE_BCK_OUT_DELAY 0x00000003 143 | #define I2S_RECE_BCK_OUT_DELAY_S 18 144 | #define I2S_RECE_WS_OUT_DELAY 0x00000003 145 | #define I2S_RECE_WS_OUT_DELAY_S 16 146 | #define I2S_TRANS_SD_OUT_DELAY 0x00000003 147 | #define I2S_TRANS_SD_OUT_DELAY_S 14 148 | #define I2S_TRANS_WS_OUT_DELAY 0x00000003 149 | #define I2S_TRANS_WS_OUT_DELAY_S 12 150 | #define I2S_TRANS_BCK_OUT_DELAY 0x00000003 151 | #define I2S_TRANS_BCK_OUT_DELAY_S 10 152 | #define I2S_RECE_SD_IN_DELAY 0x00000003 153 | #define I2S_RECE_SD_IN_DELAY_S 8 154 | #define I2S_RECE_WS_IN_DELAY 0x00000003 155 | #define I2S_RECE_WS_IN_DELAY_S 6 156 | #define I2S_RECE_BCK_IN_DELAY 0x00000003 157 | #define I2S_RECE_BCK_IN_DELAY_S 4 158 | #define I2S_TRANS_WS_IN_DELAY 0x00000003 159 | #define I2S_TRANS_WS_IN_DELAY_S 2 160 | #define I2S_TRANS_BCK_IN_DELAY 0x00000003 161 | #define I2S_TRANS_BCK_IN_DELAY_S 0 162 | 163 | #define I2S_FIFO_CONF (DR_REG_I2S_BASE + 0x0020) 164 | #define I2S_I2S_RX_FIFO_MOD 0x00000007 165 | #define I2S_I2S_RX_FIFO_MOD_S 16 166 | #define I2S_I2S_TX_FIFO_MOD 0x00000007 167 | #define I2S_I2S_TX_FIFO_MOD_S 13 168 | #define I2S_I2S_DSCR_EN (BIT(12)) 169 | #define I2S_I2S_TX_DATA_NUM 0x0000003F 170 | #define I2S_I2S_TX_DATA_NUM_S 6 171 | #define I2S_I2S_RX_DATA_NUM 0x0000003F 172 | #define I2S_I2S_RX_DATA_NUM_S 0 173 | 174 | 175 | #define I2SRXEOF_NUM (DR_REG_I2S_BASE + 0x0024) 176 | #define I2S_I2S_RX_EOF_NUM 0xFFFFFFFF 177 | #define I2S_I2S_RX_EOF_NUM_S 0 178 | 179 | #define I2SCONF_SIGLE_DATA (DR_REG_I2S_BASE + 0x0028) 180 | #define I2S_I2S_SIGLE_DATA 0xFFFFFFFF 181 | #define I2S_I2S_SIGLE_DATA_S 0 182 | 183 | #define I2SCONF_CHAN (DR_REG_I2S_BASE + 0x002c) 184 | #define I2S_RX_CHAN_MOD 0x00000003 185 | #define I2S_RX_CHAN_MOD_S 3 186 | #define I2S_TX_CHAN_MOD 0x00000007 187 | #define I2S_TX_CHAN_MOD_S 0 188 | 189 | 190 | //From sdio_slv.h 191 | 192 | 193 | struct sdio_queue 194 | { 195 | uint32 blocksize:12; 196 | uint32 datalen:12; 197 | uint32 unused:5; 198 | uint32 sub_sof:1; 199 | uint32 eof:1; 200 | uint32 owner:1; 201 | 202 | uint32 buf_ptr; 203 | uint32 next_link_ptr; 204 | }; 205 | 206 | struct sdio_slave_status_element 207 | { 208 | uint32 wr_busy:1; 209 | uint32 rd_empty :1; 210 | uint32 comm_cnt :3; 211 | uint32 intr_no :3; 212 | uint32 rx_length:16; 213 | uint32 res:8; 214 | }; 215 | 216 | union sdio_slave_status 217 | { 218 | struct sdio_slave_status_element elm_value; 219 | uint32 word_value; 220 | }; 221 | 222 | #define RX_AVAILIBLE 2 223 | #define TX_AVAILIBLE 1 224 | #define INIT_STAGE 0 225 | 226 | #define SDIO_QUEUE_LEN 8 227 | #define MOSI 0 228 | #define MISO 1 229 | #define SDIO_DATA_ERROR 6 230 | 231 | #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) 232 | #define TRIG_TOHOST_INT() SET_PERI_REG_MASK(SLC_INTVEC_TOHOST , BIT0);\ 233 | CLEAR_PERI_REG_MASK(SLC_INTVEC_TOHOST , BIT0) 234 | 235 | 236 | ///Rest of program... 237 | 238 | //Pointer to the I2S DMA buffer data 239 | //static unsigned int i2sBuf[I2SDMABUFCNT][I2SDMABUFLEN]; 240 | //I2S DMA buffer descriptors 241 | //static struct sdio_queue i2sBufDesc[I2SDMABUFCNT]; 242 | static struct sdio_queue i2sBufDescOut; 243 | static struct sdio_queue i2sBufDescZeroes; 244 | 245 | static unsigned int i2sZeroes[32]; 246 | static unsigned int i2sBlock[WS_BLOCKSIZE/4]; 247 | 248 | //Queue which contains empty DMA buffers 249 | //DMA underrun counter 250 | 251 | 252 | #ifdef USE_2812_INTERRUPTS 253 | 254 | volatile uint8_t ws2812_dma_complete; 255 | 256 | //This routine is called as soon as the DMA routine has something to tell us. All we 257 | //handle here is the RX_EOF_INT status, which indicate the DMA has sent a buffer whose 258 | //descriptor has the 'EOF' field set to 1. 259 | LOCAL void slc_isr(void) { 260 | //clear all intr flags 261 | // WRITE_PERI_REG(SLC_INT_CLR, 0xffffffff);//slc_intr_status); 262 | 263 | // ws2812_dma_complete = 1; 264 | 265 | //This is a little wacky. This function actually gets called twice. 266 | //Once for the initial transfer, but by the time we tell it to stop 267 | //The other zero transfer's already begun. 268 | // SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_STOP); 269 | } 270 | 271 | 272 | #endif 273 | 274 | //Initialize I2S subsystem for DMA circular buffer use 275 | void ICACHE_FLASH_ATTR ws2812_init() 276 | { 277 | int x, y; 278 | 279 | //Reset DMA 280 | SET_PERI_REG_MASK(SLC_CONF0, SLC_RXLINK_RST);//|SLC_TXLINK_RST); 281 | CLEAR_PERI_REG_MASK(SLC_CONF0, SLC_RXLINK_RST);//|SLC_TXLINK_RST); 282 | 283 | //Clear DMA int flags 284 | SET_PERI_REG_MASK(SLC_INT_CLR, 0xffffffff); 285 | CLEAR_PERI_REG_MASK(SLC_INT_CLR, 0xffffffff); 286 | 287 | //Enable and configure DMA 288 | CLEAR_PERI_REG_MASK(SLC_CONF0, (SLC_MODE< WS_BLOCKSIZE ) return; 450 | 451 | int pl = 0; 452 | int quit = 0; 453 | 454 | //Once for each led. 455 | for( place = 0; !quit; place++ ) 456 | { 457 | uint8_t b; 458 | b = buffer[pl++]; uint16_t c1a = bitpatterns[(b&0x0f)]; uint16_t c1b = bitpatterns[(b>>4)]; 459 | b = buffer[pl++]; uint16_t c2a = bitpatterns[(b&0x0f)]; uint16_t c2b = bitpatterns[(b>>4)]; 460 | b = buffer[pl++]; uint16_t c3a = bitpatterns[(b&0x0f)]; uint16_t c3b = bitpatterns[(b>>4)]; 461 | b = buffer[pl++]; uint16_t c4a = bitpatterns[(b&0x0f)]; uint16_t c4b = bitpatterns[(b>>4)]; 462 | 463 | if( pl >= buffersize ) 464 | { 465 | quit = 1; 466 | if( pl-1 >= buffersize ) c4a = c4b = 0; 467 | if( pl-2 >= buffersize ) c3a = c3b = 0; 468 | if( pl-3 >= buffersize ) c2a = c2b = 0; 469 | if( pl-4 >= buffersize ) c1a = c1b = 0; 470 | } 471 | 472 | //Order of bits on wire: Reverse from how they appear here. 473 | #define STEP1(x) (c##x##b >> 4 ) 474 | #define STEP2(x) ((c##x##b << 4 ) | ( c##x##a>>8 )) 475 | #define STEP3(x) (c##x##a & 0xff ) 476 | 477 | *(bufferpl++) = STEP1(2); 478 | *(bufferpl++) = STEP3(1); 479 | *(bufferpl++) = STEP2(1); 480 | *(bufferpl++) = STEP1(1); 481 | 482 | *(bufferpl++) = STEP2(3); 483 | *(bufferpl++) = STEP1(3); 484 | *(bufferpl++) = STEP3(2); 485 | *(bufferpl++) = STEP2(2); 486 | 487 | *(bufferpl++) = STEP3(4); 488 | *(bufferpl++) = STEP2(4); 489 | *(bufferpl++) = STEP1(4); 490 | *(bufferpl++) = STEP3(3); 491 | } 492 | 493 | while( bufferpl < &((uint8_t*)i2sBlock)[WS_BLOCKSIZE] ) *(bufferpl++) = 0; 494 | 495 | #elif defined(WS2812_FOUR_SAMPLE) || defined(SK6812) 496 | uint16_t * bufferpl = (uint16_t*)&i2sBlock[0]; 497 | 498 | if( buffersize * 4 > WS_BLOCKSIZE ) return; 499 | 500 | for( place = 0; place < buffersize; place++ ) 501 | { 502 | uint8_t btosend = buffer[place]; 503 | *(bufferpl++) = bitpatterns[(btosend&0x0f)]; 504 | *(bufferpl++) = bitpatterns[(btosend>>4)&0x0f]; 505 | } 506 | #endif 507 | 508 | #ifdef USE_2812_INTERRUPTS 509 | 510 | uint16_t leftover = buffersize & 0x1f; 511 | if( leftover ) leftover = 32 - leftover; 512 | for( place = 0; place < leftover; place++ ) 513 | { 514 | *(bufferpl++) = 0; 515 | *(bufferpl++) = 0; 516 | } 517 | 518 | buffersize += leftover; 519 | 520 | uint16_t sizeout_words = buffersize * 2; 521 | 522 | i2sBufDescOut.owner = 1; 523 | i2sBufDescOut.eof = 1; 524 | i2sBufDescOut.sub_sof = 0; 525 | i2sBufDescOut.datalen = sizeout_words*2; //Size (in bytes) 526 | i2sBufDescOut.blocksize = sizeout_words*2; //Size (in bytes) 527 | i2sBufDescOut.buf_ptr = (uint32_t)&i2sBlock[0]; 528 | i2sBufDescOut.unused = 0; 529 | i2sBufDescOut.next_link_ptr=(uint32_t)&i2sBufDescZeroes; //At the end, just redirect the DMA to the zero buffer. 530 | 531 | SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_STOP); 532 | CLEAR_PERI_REG_MASK(SLC_RX_LINK,SLC_RXLINK_DESCADDR_MASK); 533 | SET_PERI_REG_MASK(SLC_RX_LINK, ((uint32)&i2sBufDescOut) & SLC_RXLINK_DESCADDR_MASK); 534 | SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_START); 535 | 536 | #endif 537 | 538 | } 539 | 540 | 541 | 542 | --------------------------------------------------------------------------------