From 758a5cc39dfd13f9cf645798a1f55f3f3f6eb317 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Fri, 30 Nov 2018 07:01:36 -0500 Subject: [PATCH] stab at the esp8266 port --- embedded8266/ccconfig.h | 4 +- embedded8266/esp82xx | 2 +- embedded8266/image.elf-0x00000.bin | Bin 33904 -> 34256 bytes embedded8266/user.cfg | 3 +- embedded8266/user/custom_commands.c | 12 +- embedded8266/user/user_main.c | 10 +- embedded8266/user/ws2812_i2s.c | 187 +++++++++++++++++++++++----- embedded8266/user/ws2812_i2s.h | 8 +- 8 files changed, 182 insertions(+), 44 deletions(-) diff --git a/embedded8266/ccconfig.h b/embedded8266/ccconfig.h index 299949e..b32d2a6 100644 --- a/embedded8266/ccconfig.h +++ b/embedded8266/ccconfig.h @@ -6,7 +6,7 @@ #define HPABUFFSIZE 512 #define CCEMBEDDED -#define NUM_LIN_LEDS 255 +#define NUM_LIN_LEDS 541 #define DFREQ 16000 #define memcpy ets_memcpy @@ -30,6 +30,7 @@ #define COLORCHORD_OUTPUT_DRIVER CCS.gCOLORCHORD_OUTPUT_DRIVER #define COLORCHORD_ACTIVE CCS.gCOLORCHORD_ACTIVE #define INITIAL_AMP CCS.gINITIAL_AMP +#define LED_DRIVER_MODE CCS.gLED_DRIVER_MODE //We are not enabling these for the ESP8266 port. #define LIN_WRAPAROUND 0 @@ -55,6 +56,7 @@ struct CCSettings uint16_t gUSE_NUM_LIN_LEDS; // = NUM_LIN_LEDS uint16_t gCOLORCHORD_ACTIVE; uint16_t gCOLORCHORD_OUTPUT_DRIVER; + uint16_t gLED_DRIVER_MODE; uint16_t gINITIAL_AMP; }; diff --git a/embedded8266/esp82xx b/embedded8266/esp82xx index b0c4a01..a08b471 160000 --- a/embedded8266/esp82xx +++ b/embedded8266/esp82xx @@ -1 +1 @@ -Subproject commit b0c4a01a4a344054f70b936d448fd0fd6c15ad20 +Subproject commit a08b47184b3fcf04172ecc0b6a1aee9c90e5d92d diff --git a/embedded8266/image.elf-0x00000.bin b/embedded8266/image.elf-0x00000.bin index cc74d6ca5de2b1e12529b7247544d3c4ca6d4ebb..fcf1e8d2a0357a807f52d27f6423a53b3358d6bd 100644 GIT binary patch delta 3612 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 WKymKk@WfkiNXGBj=+u4x?f!qmxo{c) delta 3223 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 diff --git a/embedded8266/user.cfg b/embedded8266/user.cfg index 2b0562e..9463bb5 100644 --- a/embedded8266/user.cfg +++ b/embedded8266/user.cfg @@ -15,7 +15,7 @@ ESP_GCC_VERS = 4.8.5 #SDK = $(HOME)/esp8266/esp_iot_sdk_v1.5.2 PAGE_SCRIPTS = main.js -FWBURNFLAGS = -b 2000000 +FWBURNFLAGS = -b 1500000 OPTS += -DUSE_OPTIMIZE_PRINTF OPTS += -DMFS_PAGE_OFFSET=$(MFS_PAGE_OFFSET) @@ -28,6 +28,7 @@ OPTS += -DDISABLE_NET_REFLASH #OPTS += -DVERIFY_FLASH_WRITE #OPTS += -DDEBUG #OPTS += -DFREQ=12500 +OPTS += -DSOFTAP_CHANNEL=6 STRIPPED_LIBGCC=YES diff --git a/embedded8266/user/custom_commands.c b/embedded8266/user/custom_commands.c index 8fb9a7b..c06e65b 100644 --- a/embedded8266/user/custom_commands.c +++ b/embedded8266/user/custom_commands.c @@ -11,28 +11,28 @@ extern volatile uint8_t sounddata[]; extern volatile uint16_t soundhead; -#define CONFIGURABLES 18 //(plus1) +#define CONFIGURABLES 19 //(plus1) struct SaveLoad { - uint8_t configs[CONFIGURABLES]; - uint8_t SaveLoadKey; //Must be 0xaa to be valid. + uint16_t configs[CONFIGURABLES]; + uint16_t SaveLoadKey; //Must be 0xaa to be valid. } settings; struct CCSettings CCS; -uint16_t gConfigDefaults[CONFIGURABLES] = { 0, 6, 1, 2, 3, 4, 7, 4, 2, 80, 64, 12, 15, NUM_LIN_LEDS, 1, 0, 16, 0 }; +uint16_t gConfigDefaults[CONFIGURABLES] = { 0, 6, 1, 2, 3, 4, 7, 4, 2, 80, 64, 12, 15, NUM_LIN_LEDS, 1, 0, 16, 0, 0 }; uint16_t * gConfigurables[CONFIGURABLES] = { &CCS.gROOT_NOTE_OFFSET, &CCS.gDFTIIR, &CCS.gFUZZ_IIR_BITS, &CCS.gFILTER_BLUR_PASSES, &CCS.gSEMIBITSPERBIN, &CCS.gMAX_JUMP_DISTANCE, &CCS.gMAX_COMBINE_DISTANCE, &CCS.gAMP_1_IIR_BITS, &CCS.gAMP_2_IIR_BITS, &CCS.gMIN_AMP_FOR_NOTE, &CCS.gMINIMUM_AMP_FOR_NOTE_TO_DISAPPEAR, &CCS.gNOTE_FINAL_AMP, - &CCS.gNERF_NOTE_PORP, &CCS.gUSE_NUM_LIN_LEDS, &CCS.gCOLORCHORD_ACTIVE, &CCS.gCOLORCHORD_OUTPUT_DRIVER, &CCS.gINITIAL_AMP, 0 }; + &CCS.gNERF_NOTE_PORP, &CCS.gUSE_NUM_LIN_LEDS, &CCS.gCOLORCHORD_ACTIVE, &CCS.gCOLORCHORD_OUTPUT_DRIVER, &CCS.gINITIAL_AMP, &CCS.gLED_DRIVER_MODE, 0 }; char * gConfigurableNames[CONFIGURABLES] = { "gROOT_NOTE_OFFSET", "gDFTIIR", "gFUZZ_IIR_BITS", "gFILTER_BLUR_PASSES", "gSEMIBITSPERBIN", "gMAX_JUMP_DISTANCE", "gMAX_COMBINE_DISTANCE", "gAMP_1_IIR_BITS", "gAMP_2_IIR_BITS", "gMIN_AMP_FOR_NOTE", "gMINIMUM_AMP_FOR_NOTE_TO_DISAPPEAR", "gNOTE_FINAL_AMP", - "gNERF_NOTE_PORP", "gUSE_NUM_LIN_LEDS", "gCOLORCHORD_ACTIVE", "gCOLORCHORD_OUTPUT_DRIVER", "gINITIAL_AMP", 0 }; + "gNERF_NOTE_PORP", "gUSE_NUM_LIN_LEDS", "gCOLORCHORD_ACTIVE", "gCOLORCHORD_OUTPUT_DRIVER", "gINITIAL_AMP", "gLED_DRIVER_MODE", 0 }; void ICACHE_FLASH_ATTR CustomStart( ) { diff --git a/embedded8266/user/user_main.c b/embedded8266/user/user_main.c index fb76c57..6ed9c5b 100644 --- a/embedded8266/user/user_main.c +++ b/embedded8266/user/user_main.c @@ -62,7 +62,7 @@ static void NewFrame() break; }; - ws2812_push( ledOut, USE_NUM_LIN_LEDS * 3 ); + ws2812_push( ledOut, USE_NUM_LIN_LEDS * 3, LED_DRIVER_MODE ); } os_event_t procTaskQueue[procTaskQueueLen]; @@ -151,7 +151,7 @@ static void ICACHE_FLASH_ATTR myTimer(void *arg) // 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 ); +// ws2812_push( ledout, 6, LED_DRIVER_MODE ); } @@ -162,7 +162,7 @@ static void ICACHE_FLASH_ATTR udpserver_recv(void *arg, char *pusrdata, unsigned // uint8_t buffer[MAX_FRAME]; // uint8_t ledout[] = { 0x00, 0xff, 0xaa, 0x00, 0xff, 0xaa, }; uart0_sendStr("X"); - ws2812_push( pusrdata+3, len ); + ws2812_push( pusrdata+3, len, LED_DRIVER_MODE ); } void ICACHE_FLASH_ATTR charrx( uint8_t c ) @@ -216,6 +216,7 @@ void ICACHE_FLASH_ATTR user_init(void) os_timer_arm(&some_timer, 100, 1); //Set GPIO16 for Input +#if 0 WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | (uint32)0x1); // mux configuration for XPD_DCDC and rtc_gpio0 connection @@ -224,6 +225,9 @@ void ICACHE_FLASH_ATTR user_init(void) WRITE_PERI_REG(RTC_GPIO_ENABLE, READ_PERI_REG(RTC_GPIO_ENABLE) & (uint32)0xfffffffe); //out disable +#endif + + system_update_cpu_freq(SYS_CPU_160MHZ); InitColorChord(); //Init colorchord diff --git a/embedded8266/user/ws2812_i2s.c b/embedded8266/user/ws2812_i2s.c index f2e018b..fb41186 100644 --- a/embedded8266/user/ws2812_i2s.c +++ b/embedded8266/user/ws2812_i2s.c @@ -45,6 +45,13 @@ Extra copyright info: //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 LUXETRON + +#ifdef LUXETRON +#define INVERT +#define WS_I2S_BCK 14 +#define WS_I2S_DIV 5 +#else #ifdef WS2812_THREE_SAMPLE #define WS_I2S_BCK 22 //Seems to work as low as 19, but is shakey at 18. @@ -55,6 +62,7 @@ Extra copyright info: #else #error You need to either define WS2812_THREE_SAMPLE or WS2812_FOUR_SAMPLE #endif +#endif #ifndef i2c_bbpll #define i2c_bbpll 0x67 @@ -239,11 +247,13 @@ union sdio_slave_status //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 i2sBufDescOut0; +static struct sdio_queue i2sBufDescOut1; +static struct sdio_queue i2sBufDescOut2; static struct sdio_queue i2sBufDescZeroes; static unsigned int i2sZeroes[32]; -static unsigned int i2sBlock[WS_BLOCKSIZE/4]; +static unsigned int i2sBlock[(WS_BLOCKSIZE0 + WS_BLOCKSIZE1 + WS_BLOCKSIZE2)/4]; //Queue which contains empty DMA buffers //DMA underrun counter @@ -290,14 +300,32 @@ void ICACHE_FLASH_ATTR ws2812_init() 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. + i2sBufDescOut0.owner = 1; + i2sBufDescOut0.eof = 1; + i2sBufDescOut0.sub_sof = 0; + i2sBufDescOut0.datalen = WS_BLOCKSIZE0; //Size (in bytes) + i2sBufDescOut0.blocksize = WS_BLOCKSIZE0; //Size (in bytes) + i2sBufDescOut0.buf_ptr=(uint32_t)&i2sBlock[0]; + i2sBufDescOut0.unused=0; + i2sBufDescOut0.next_link_ptr=(uint32_t)&i2sBufDescOut1; //At the end, just redirect the DMA to the zero buffer. + + i2sBufDescOut1.owner = 1; + i2sBufDescOut1.eof = 1; + i2sBufDescOut1.sub_sof = 0; + i2sBufDescOut1.datalen = WS_BLOCKSIZE1; //Size (in bytes) + i2sBufDescOut1.blocksize = WS_BLOCKSIZE1; //Size (in bytes) + i2sBufDescOut1.buf_ptr=(uint32_t)&i2sBlock[WS_BLOCKSIZE0/4]; + i2sBufDescOut1.unused=0; + i2sBufDescOut1.next_link_ptr=(uint32_t)&i2sBufDescOut2; //At the end, just redirect the DMA to the zero buffer. + + i2sBufDescOut2.owner = 1; + i2sBufDescOut2.eof = 1; + i2sBufDescOut2.sub_sof = 0; + i2sBufDescOut2.datalen = WS_BLOCKSIZE2; //Size (in bytes) + i2sBufDescOut2.blocksize = WS_BLOCKSIZE2; //Size (in bytes) + i2sBufDescOut2.buf_ptr=(uint32_t)&i2sBlock[(WS_BLOCKSIZE1+WS_BLOCKSIZE0)/4]; + i2sBufDescOut2.unused=0; + i2sBufDescOut2.next_link_ptr=(uint32_t)&i2sBufDescZeroes; //At the end, just redirect the DMA to the zero buffer. i2sBufDescZeroes.owner = 1; i2sBufDescZeroes.eof = 1; @@ -306,16 +334,24 @@ void ICACHE_FLASH_ATTR ws2812_init() i2sBufDescZeroes.blocksize = 32; i2sBufDescZeroes.buf_ptr=(uint32_t)&i2sZeroes[0]; i2sBufDescZeroes.unused=0; - i2sBufDescZeroes.next_link_ptr=(uint32_t)&i2sBufDescOut; + i2sBufDescZeroes.next_link_ptr=(uint32_t)&i2sBufDescOut0; for( x = 0; x < 32; x++ ) { +#ifdef INVERT + i2sZeroes[x] = 0xffffffff; +#else i2sZeroes[x] = 0x00; +#endif } - for( x = 0; x < WS_BLOCKSIZE/4; x++ ) + for( x = 0; x < (WS_BLOCKSIZE0+WS_BLOCKSIZE1+WS_BLOCKSIZE2)/4; x++ ) { +#ifdef INVERT i2sBlock[x] = 0x00000000;//(x == 0 || x == 999)?0xaa:0x00; +#else + i2sBlock[x] = 0xffffffff;//(x == 0 || x == 999)?0xaa:0x00; +#endif /* uint16_t * tt = (uint16_t*)&i2sBlock[x]; (*(tt+0)) = 0xA0F0; @@ -328,7 +364,7 @@ void ICACHE_FLASH_ATTR ws2812_init() // 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); + SET_PERI_REG_MASK(SLC_RX_LINK, ((uint32)&i2sBufDescOut0) & SLC_RXLINK_DESCADDR_MASK); #if USE_2812_INTERRUPTS @@ -418,6 +454,14 @@ static const uint16_t bitpatterns[16] = { }; #elif defined(WS2812_FOUR_SAMPLE) +#ifdef INVERT +static const uint16_t bitpatterns[16] = { + ~0b1000100010001000, ~0b1000100010001100, ~0b1000100011001000, ~0b1000100011001100, + ~0b1000110010001000, ~0b1000110010001100, ~0b1000110011001000, ~0b1000110011001100, + ~0b1100100010001000, ~0b1100100010001100, ~0b1100100011001000, ~0b1100100011001100, + ~0b1100110010001000, ~0b1100110010001100, ~0b1100111011001000, ~0b1100110011001100, +}; +#else //Tricky, send out WS2812 bits with coded pulses, one nibble, then the other. static const uint16_t bitpatterns[16] = { 0b1000100010001000, 0b1000100010001110, 0b1000100011101000, 0b1000100011101110, @@ -426,14 +470,17 @@ static const uint16_t bitpatterns[16] = { 0b1110111010001000, 0b1110111010001110, 0b1110111011101000, 0b1110111011101110, }; #endif +#endif -void ws2812_push( uint8_t * buffer, uint16_t buffersize ) +void ws2812_push( uint8_t * buffer, uint16_t buffersize, int driver_mode ) { uint16_t place; // while( !ws2812_dma_complete ); #ifdef WS2812_THREE_SAMPLE + if( driver_mode ) return; //Not supported in three-sample mode. + uint8_t * bufferpl = (uint8_t*)&i2sBlock[0]; // buffersize += 3; @@ -484,20 +531,76 @@ void ws2812_push( uint8_t * buffer, uint16_t buffersize ) while( bufferpl < &((uint8_t*)i2sBlock)[WS_BLOCKSIZE] ) *(bufferpl++) = 0; #elif defined(WS2812_FOUR_SAMPLE) - uint16_t * bufferpl = (uint16_t*)&i2sBlock[0]; - if( buffersize * 4 > WS_BLOCKSIZE ) return; - for( place = 0; place < buffersize; place++ ) + if( driver_mode ) { - uint8_t btosend = buffer[place]; - *(bufferpl++) = bitpatterns[(btosend&0x0f)]; - *(bufferpl++) = bitpatterns[(btosend>>4)&0x0f]; + uint16_t * bufferpl = (uint16_t*)&i2sBlock[0]; + int strips = (buffersize / 3) / 18; + int strip; + int led; + int side; + for( side = 0; side < 2; side++ ) + for( strip = 0; strip < strips; strip++ ) + { + int byte = (side | (strip<<1)) + 2; + *(bufferpl++) = bitpatterns[(byte&0x0f)]; + *(bufferpl++) = 0xffff; + *(bufferpl++) = 0xffff; + *(bufferpl++) = bitpatterns[(byte>>4)&0x0f]; + + + for( led = 0; led < 9; led++ ) + { + int inled; + if( side == 0 ) + { + inled = strip * 18 + led + 9; + } + else + { + inled = strip * 18 + 8 - led; + } + + + int g = buffer[inled*3+0]; + int r = buffer[inled*3+1]; + int b = buffer[inled*3+2]; + + int y = 0; //R G R B + + *(bufferpl++) = bitpatterns[(y&0x0f)]; + *(bufferpl++) = bitpatterns[(y>>4)&0x0f]; + *(bufferpl++) = bitpatterns[(g&0x0f)]; + *(bufferpl++) = bitpatterns[(g>>4)&0x0f]; + *(bufferpl++) = bitpatterns[(r&0x0f)]; + *(bufferpl++) = bitpatterns[(r>>4)&0x0f]; + *(bufferpl++) = bitpatterns[(b&0x0f)]; + *(bufferpl++) = bitpatterns[(b>>4)&0x0f]; + } + *(bufferpl++) = 0x0000; + *(bufferpl++) = 0xffff; + } + while( bufferpl != (uint16_t*)&i2sBlock[(WS_BLOCKSIZE0+WS_BLOCKSIZE1+WS_BLOCKSIZE2)/4] ) + *(bufferpl++) = 0xffff; } + else + { + uint16_t * bufferpl = (uint16_t*)&i2sBlock[0]; + + if( buffersize * 4 > WS_BLOCKSIZE0 + WS_BLOCKSIZE1 + WS_BLOCKSIZE2 ) return; + + for( place = 0; place < buffersize; place++ ) + { + uint8_t btosend = buffer[place]; + *(bufferpl++) = bitpatterns[(btosend&0x0f)]; + *(bufferpl++) = bitpatterns[(btosend>>4)&0x0f]; + } + } + #endif #if USE_2812_INTERRUPTS - uint16_t leftover = buffersize & 0x1f; if( leftover ) leftover = 32 - leftover; for( place = 0; place < leftover; place++ ) @@ -510,18 +613,42 @@ void ws2812_push( uint8_t * buffer, uint16_t buffersize ) 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. + int firstsize = sizeout_words, secondsize = 0; + if( sizeout_words > WS_BLOCKSIZE0 ) + { + secondsize = firstsize - (WS_BLOCKSIZE0/4); + firstsize = WS_BLOCKSIZE0/4; + } + i2sBufDescOut0.owner = 1; + i2sBufDescOut0.eof = 1; + i2sBufDescOut0.sub_sof = 0; + i2sBufDescOut0.datalen = sizeout_words*2; //Size (in bytes) + i2sBufDescOut0.blocksize = sizeout_words*2; //Size (in bytes) + i2sBufDescOut0.buf_ptr = (uint32_t)&i2sBlock[0]; + i2sBufDescOut0.unused = 0; + i2sBufDescOut0.next_link_ptr=(uint32_t)&i2sBufDescOut1; //At the end, just redirect the DMA to the zero buffer. + + i2sBufDescOut1.owner = 1; + i2sBufDescOut1.eof = 1; + i2sBufDescOut1.sub_sof = 0; + i2sBufDescOut1.datalen = sizeout_words*2; //Size (in bytes) + i2sBufDescOut1.blocksize = sizeout_words*2; //Size (in bytes) + i2sBufDescOut1.buf_ptr = (uint32_t)&i2sBlock[WS_BLOCKSIZE0/4]; + i2sBufDescOut1.unused = 0; + i2sBufDescOut1.next_link_ptr=(uint32_t)&i2sBufDescOut2; //At the end, just redirect the DMA to the zero buffer. + + i2sBufDescOut2.owner = 1; + i2sBufDescOut2.eof = 1; + i2sBufDescOut2.sub_sof = 0; + i2sBufDescOut2.datalen = sizeout_words*2; //Size (in bytes) + i2sBufDescOut2.blocksize = sizeout_words*2; //Size (in bytes) + i2sBufDescOut2.buf_ptr = (uint32_t)&i2sBlock[(WS_BLOCKSIZE0+WS_BLOCKSIZE1)/4]; + i2sBufDescOut2.unused = 0; + i2sBufDescOut2.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, ((uint32)&i2sBufDescOut0) & SLC_RXLINK_DESCADDR_MASK); SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_START); #endif diff --git a/embedded8266/user/ws2812_i2s.h b/embedded8266/user/ws2812_i2s.h index c0276e6..0115a6e 100644 --- a/embedded8266/user/ws2812_i2s.h +++ b/embedded8266/user/ws2812_i2s.h @@ -15,7 +15,9 @@ //NOTE: Blocksize MUST be divisible by 4. Cannot exceed 4092 //Each LED takes up 12 block bytes in WS2812_FOUR_SAMPLE //Or 9 block bytes in WS2812_THREE_SAMPLE -#define WS_BLOCKSIZE 4000 +#define WS_BLOCKSIZE0 4000 +#define WS_BLOCKSIZE1 4000 +#define WS_BLOCKSIZE2 4000 //You can either have 3 or 4 samples per bit for WS2812s. //3 sample can't go quite as fast as 4. @@ -28,7 +30,9 @@ //#define WS2812_FOUR_SAMPLE void ICACHE_FLASH_ATTR ws2812_init(); -void ws2812_push( uint8_t * buffer, uint16_t buffersize ); //Buffersize = Nr LEDs * 3 +void ws2812_push( uint8_t * buffer, uint16_t buffersize, int led_mode ); //Buffersize = Nr LEDs * 3 +//led_mode = 0 for WS2812B +//led_mode = 1 for luxehedron #endif