diff --git a/colorchord2/OutputCells.c b/colorchord2/OutputCells.c index 3e75392..a95d9cc 100644 --- a/colorchord2/OutputCells.c +++ b/colorchord2/OutputCells.c @@ -132,24 +132,30 @@ static void LEDUpdate(void * id, struct NoteFinder*nf) if( led->led_note_attached[j] != -1 ) continue; if( !led->timebased ) { selindex = j; break; } - float bias = 0; - float timeimp = 1; if( led->snakey ) { -// bias = (j - led->snakeyplace + led->total_leds+(rand()%100)*.01); -// if( bias > led->total_leds ) bias -= led->total_leds; + float bias = 0; + float timeimp = 1; bias = (j - led->snakeyplace + led->total_leds) % led->total_leds; if( bias > led->total_leds / 2 ) bias = led->total_leds - bias + 1; timeimp = 0; - } - float score = led->time_of_change[j] * timeimp + bias; - if( score < seltime ) + float score = led->time_of_change[j] * timeimp + bias; + if( score < seltime ) + { + seltime = score; + selindex = j; + } + } + else { - seltime = score; - selindex = j; + if( led->time_of_change[j] < seltime ) + { + seltime = led->time_of_change[j]; + selindex = j; + } } } if( selindex >= 0 ) diff --git a/colorchord2/dodecahedron.conf b/colorchord2/dodecahedron.conf index 6e4eee2..ba955ea 100644 --- a/colorchord2/dodecahedron.conf +++ b/colorchord2/dodecahedron.conf @@ -9,6 +9,9 @@ steady_bright = 0 rgby = 1 sourcename = alsa_output.pci-0000_00_1f.3.analog-stereo.monitor +#sourcename = default + + #alsa_output.pci-0000_01_00.1.hdmi-stereo.monitor # alsa_output.pci-0000_01_00.1.hdmi-stereo-extra1.monitor #alsa_output.pci-0000_00_1f.3.analog-stereo.monitor @@ -16,12 +19,12 @@ skipfirst = 0 firstval = 0 port = 7777 -address = 192.168.3.192 +address = 192.168.11.157 slope=.10 amplify=.5 -qtyamp=50 +qtyamp=120 timebased=1 diff --git a/embedded8266/ccconfig.h b/embedded8266/ccconfig.h index 02b9c33..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 @@ -38,26 +39,29 @@ struct CCSettings { - uint8_t gSETTINGS_KEY; - uint8_t gROOT_NOTE_OFFSET; //Set to define what the root note is. 0 = A. - uint8_t gDFTIIR; //=6 - uint8_t gFUZZ_IIR_BITS; //=1 - uint8_t gFILTER_BLUR_PASSES; //=2 - uint8_t gSEMIBITSPERBIN; //=3 - uint8_t gMAX_JUMP_DISTANCE; //=4 - uint8_t gMAX_COMBINE_DISTANCE; //=7 - uint8_t gAMP_1_IIR_BITS; //=4 - uint8_t gAMP_2_IIR_BITS; //=2 - uint8_t gMIN_AMP_FOR_NOTE; //=80 - uint8_t gMINIMUM_AMP_FOR_NOTE_TO_DISAPPEAR; //=64 - uint8_t gNOTE_FINAL_AMP; //=12 - uint8_t gNERF_NOTE_PORP; //=15 - uint8_t gUSE_NUM_LIN_LEDS; // = NUM_LIN_LEDS - uint8_t gCOLORCHORD_ACTIVE; - uint8_t gCOLORCHORD_OUTPUT_DRIVER; - uint8_t gINITIAL_AMP; + uint16_t gSETTINGS_KEY; + uint16_t gROOT_NOTE_OFFSET; //Set to define what the root note is. 0 = A. + uint16_t gDFTIIR; //=6 + uint16_t gFUZZ_IIR_BITS; //=1 + uint16_t gFILTER_BLUR_PASSES; //=2 + uint16_t gSEMIBITSPERBIN; //=3 + uint16_t gMAX_JUMP_DISTANCE; //=4 + uint16_t gMAX_COMBINE_DISTANCE; //=7 + uint16_t gAMP_1_IIR_BITS; //=4 + uint16_t gAMP_2_IIR_BITS; //=2 + uint16_t gMIN_AMP_FOR_NOTE; //=80 + uint16_t gMINIMUM_AMP_FOR_NOTE_TO_DISAPPEAR; //=64 + uint16_t gNOTE_FINAL_AMP; //=12 + uint16_t gNERF_NOTE_PORP; //=15 + 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; }; +#define CCCONFIG_ADDRESS 0xAF000 + extern struct CCSettings CCS; 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 53f421a..fcf1e8d 100644 Binary files a/embedded8266/image.elf-0x00000.bin and b/embedded8266/image.elf-0x00000.bin differ diff --git a/embedded8266/image.elf-0x40000.bin b/embedded8266/image.elf-0x40000.bin deleted file mode 100644 index bf9953d..0000000 Binary files a/embedded8266/image.elf-0x40000.bin and /dev/null differ diff --git a/embedded8266/user.cfg b/embedded8266/user.cfg index 923a30e..9463bb5 100644 --- a/embedded8266/user.cfg +++ b/embedded8266/user.cfg @@ -8,24 +8,29 @@ PORT = /dev/ttyUSB0 # could also be /dev/ttyACM0 WEB_PORT = 80 COM_PORT = 7777 BACKEND_PORT = 7878 -PAGE_OFFSET = 65536 # 1048576 +MFS_PAGE_OFFSET = 532480 # 0x82000 #SDK_DEFAULT = $(HOME)/esp8266/esp-open-sdk 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) OPTS += -DICACHE_FLASH -OPTS += -DDISABLE_CHARRX #Saves about 48 bytes. -OPTS += -DQUIET_REFLASH #Saves about 128 bytes. +OPTS += -DDISABLE_CHARRX #Saves about 300 bytes. +OPTS += -DQUIET_REFLASH #Saves about 96 bytes. OPTS += -DWS2812_FOUR_SAMPLE #Saves about 224 bytes. #OPTS += -DWS2812_THREE_SAMPLE - +OPTS += -DDISABLE_NET_REFLASH #OPTS += -DVERIFY_FLASH_WRITE #OPTS += -DDEBUG #OPTS += -DFREQ=12500 +OPTS += -DSOFTAP_CHANNEL=6 + +STRIPPED_LIBGCC=YES PAGE_TITLE = ColorChord Control Panel PAGE_SCRIPT = diff --git a/embedded8266/user/custom_commands.c b/embedded8266/user/custom_commands.c index 3a04c75..c06e65b 100644 --- a/embedded8266/user/custom_commands.c +++ b/embedded8266/user/custom_commands.c @@ -11,33 +11,33 @@ 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; -uint8_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 }; -uint8_t * gConfigurables[CONFIGURABLES] = { &CCS.gROOT_NOTE_OFFSET, &CCS.gDFTIIR, &CCS.gFUZZ_IIR_BITS, &CCS.gFILTER_BLUR_PASSES, +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( ) { int i; - spi_flash_read( 0x3D000, (uint32*)&settings, sizeof( settings ) ); + spi_flash_read( CCCONFIG_ADDRESS, (uint32*)&settings, sizeof( settings ) ); if( settings.SaveLoadKey == 0xaa ) { for( i = 0; i < CONFIGURABLES; i++ ) @@ -202,8 +202,8 @@ int ICACHE_FLASH_ATTR CustomCommand(char * buffer, int retsize, char *pusrdata, EnterCritical(); ets_intr_lock(); - spi_flash_erase_sector( 0x3D000/4096 ); - spi_flash_write( 0x3D000, (uint32*)&settings, ((sizeof( settings )-1)&(~0xf))+0x10 ); + spi_flash_erase_sector( CCCONFIG_ADDRESS/4096 ); + spi_flash_write( CCCONFIG_ADDRESS, (uint32*)&settings, ((sizeof( settings )-1)&(~0xf))+0x10 ); ets_intr_unlock(); ExitCritical(); diff --git a/embedded8266/user/user_main.c b/embedded8266/user/user_main.c index 7c0dcab..6ed9c5b 100644 --- a/embedded8266/user/user_main.c +++ b/embedded8266/user/user_main.c @@ -29,7 +29,7 @@ #define procTaskQueueLen 1 struct CCSettings CCS; -static volatile os_timer_t some_timer; +static os_timer_t some_timer; static struct espconn *pUdpServer; void EnterCritical(); @@ -43,10 +43,6 @@ static uint8_t hpa_running = 0; static uint8_t hpa_is_paused_for_wifi; void ICACHE_FLASH_ATTR CustomStart( ); -void ICACHE_FLASH_ATTR user_rf_pre_init() -{ -} - //Call this once we've stacked together one full colorchord frame. static void NewFrame() @@ -66,13 +62,17 @@ 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]; uint32_t samp_iir = 0; int wf = 0; + +void fpm_wakup_cb_func1(void) { wifi_fpm_close(); } + + //Tasks that happen all the time. static void procTask(os_event_t *events) @@ -119,7 +119,6 @@ static void procTask(os_event_t *events) { CSTick( 0 ); } - } //Timer event. @@ -127,6 +126,21 @@ static void ICACHE_FLASH_ATTR myTimer(void *arg) { CSTick( 1 ); + if( GPIO_INPUT_GET( 0 ) == 0 ) + { + if( system_get_rst_info()->reason != 5 ) //See if we're booting from deep sleep. (5 = deep sleep, 4 = reboot, 0 = fresh boot) + { + system_deep_sleep_set_option(4); //Option 4 = When rebooting from deep sleep, totally disable wifi. + system_deep_sleep(2000); + } + else + { + //system_deep_sleep_set_option(1); //Option 1 = Reboot with radio recalibration and wifi on. + //system_deep_sleep(2000); + system_restart(); + } + } + if( hpa_is_paused_for_wifi && printed_ip ) { StartHPATimer(); //Init the high speed ADC timer. @@ -137,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 ); } @@ -148,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 ) @@ -156,7 +170,6 @@ void ICACHE_FLASH_ATTR charrx( uint8_t c ) //Called from UART. } - void ICACHE_FLASH_ATTR user_init(void) { uart_init(BIT_RATE_115200, BIT_RATE_115200); @@ -192,7 +205,7 @@ void ICACHE_FLASH_ATTR user_init(void) while(1) { uart0_sendStr( "\r\nFAULT\r\n" ); } } - CSInit(); + CSInit( 1 ); //Add a process system_os_task(procTask, procTaskPrio, procTaskQueue, procTaskQueueLen); @@ -203,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 @@ -211,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 @@ -227,25 +244,135 @@ void ICACHE_FLASH_ATTR user_init(void) ws2812_init(); + printf( "RST REASON: %d\n", system_get_rst_info()->reason ); + // Attempt to make ADC more stable // https://github.com/esp8266/Arduino/issues/2070 // see peripherals https://espressif.com/en/support/explore/faq - //wifi_set_sleep_type(NONE_SLEEP_T); // on its own stopped wifi working + wifi_set_sleep_type(MODEM_SLEEP_T); // on its own stopped wifi working? //wifi_fpm_set_sleep_type(NONE_SLEEP_T); // with this seemed no difference system_os_post(procTaskPrio, 0, 0 ); } -void EnterCritical() +void ICACHE_FLASH_ATTR EnterCritical() { PauseHPATimer(); //ets_intr_lock(); } -void ExitCritical() +void ICACHE_FLASH_ATTR ExitCritical() { //ets_intr_unlock(); ContinueHPATimer(); } + + + +/*============================================================================== + * Partition Map Data + *============================================================================*/ + +#define SYSTEM_PARTITION_OTA_SIZE_OPT2 0x6A000 +#define SYSTEM_PARTITION_OTA_2_ADDR_OPT2 0x81000 +#define SYSTEM_PARTITION_RF_CAL_ADDR_OPT2 0xfb000 +#define SYSTEM_PARTITION_PHY_DATA_ADDR_OPT2 0xfc000 +#define SYSTEM_PARTITION_SYSTEM_PARAMETER_ADDR_OPT2 0xfd000 +#define SYSTEM_PARTITION_CUSTOMER_PRIV_PARAM_ADDR_OPT2 0x7c000 +#define SPI_FLASH_SIZE_MAP_OPT2 2 + +#define SYSTEM_PARTITION_OTA_SIZE_OPT3 0x6A000 +#define SYSTEM_PARTITION_OTA_2_ADDR_OPT3 0x81000 +#define SYSTEM_PARTITION_RF_CAL_ADDR_OPT3 0x1fb000 +#define SYSTEM_PARTITION_PHY_DATA_ADDR_OPT3 0x1fc000 +#define SYSTEM_PARTITION_SYSTEM_PARAMETER_ADDR_OPT3 0x1fd000 +#define SYSTEM_PARTITION_CUSTOMER_PRIV_PARAM_ADDR_OPT3 0x7c000 +#define SPI_FLASH_SIZE_MAP_OPT3 3 + +#define SYSTEM_PARTITION_OTA_SIZE_OPT4 0x6A000 +#define SYSTEM_PARTITION_OTA_2_ADDR_OPT4 0x81000 +#define SYSTEM_PARTITION_RF_CAL_ADDR_OPT4 0x3fb000 +#define SYSTEM_PARTITION_PHY_DATA_ADDR_OPT4 0x3fc000 +#define SYSTEM_PARTITION_SYSTEM_PARAMETER_ADDR_OPT4 0x3fd000 +#define SYSTEM_PARTITION_CUSTOMER_PRIV_PARAM_ADDR_OPT4 0x7c000 +#define SPI_FLASH_SIZE_MAP_OPT4 4 + +#define SYSTEM_PARTITION_CUSTOMER_PRIV_PARAM SYSTEM_PARTITION_CUSTOMER_BEGIN +#define EAGLE_FLASH_BIN_ADDR SYSTEM_PARTITION_CUSTOMER_BEGIN + 1 +#define EAGLE_IROM0TEXT_BIN_ADDR SYSTEM_PARTITION_CUSTOMER_BEGIN + 2 + +static const partition_item_t partition_table_opt2[] = +{ + { EAGLE_FLASH_BIN_ADDR, 0x00000, 0x10000}, + { EAGLE_IROM0TEXT_BIN_ADDR, 0x10000, 0x60000}, + { SYSTEM_PARTITION_RF_CAL, SYSTEM_PARTITION_RF_CAL_ADDR_OPT2, 0x1000}, + { SYSTEM_PARTITION_PHY_DATA, SYSTEM_PARTITION_PHY_DATA_ADDR_OPT2, 0x1000}, + { SYSTEM_PARTITION_SYSTEM_PARAMETER, SYSTEM_PARTITION_SYSTEM_PARAMETER_ADDR_OPT2, 0x3000}, +}; + +static const partition_item_t partition_table_opt3[] = +{ + { EAGLE_FLASH_BIN_ADDR, 0x00000, 0x10000}, + { EAGLE_IROM0TEXT_BIN_ADDR, 0x10000, 0x60000}, + { SYSTEM_PARTITION_RF_CAL, SYSTEM_PARTITION_RF_CAL_ADDR_OPT3, 0x1000}, + { SYSTEM_PARTITION_PHY_DATA, SYSTEM_PARTITION_PHY_DATA_ADDR_OPT3, 0x1000}, + { SYSTEM_PARTITION_SYSTEM_PARAMETER, SYSTEM_PARTITION_SYSTEM_PARAMETER_ADDR_OPT3, 0x3000}, +}; + +static const partition_item_t partition_table_opt4[] = +{ + { EAGLE_FLASH_BIN_ADDR, 0x00000, 0x10000}, + { EAGLE_IROM0TEXT_BIN_ADDR, 0x10000, 0x60000}, + { SYSTEM_PARTITION_RF_CAL, SYSTEM_PARTITION_RF_CAL_ADDR_OPT4, 0x1000}, + { SYSTEM_PARTITION_PHY_DATA, SYSTEM_PARTITION_PHY_DATA_ADDR_OPT4, 0x1000}, + { SYSTEM_PARTITION_SYSTEM_PARAMETER, SYSTEM_PARTITION_SYSTEM_PARAMETER_ADDR_OPT4, 0x3000}, +}; + + + +/** + * This is called on boot for versions ESP8266_NONOS_SDK_v1.5.2 to + * ESP8266_NONOS_SDK_v2.2.1. system_phy_set_rfoption() may be called here + */ +void user_rf_pre_init(void) +{ + ; // nothing +} + +/** + * Required function as of ESP8266_NONOS_SDK_v3.0.0. Must call + * system_partition_table_regist(). This tries to register a few different + * partition maps. The ESP should be happy with one of them. + */ +void ICACHE_FLASH_ATTR user_pre_init(void) +{ + if(system_partition_table_regist( + partition_table_opt2, + sizeof(partition_table_opt2) / sizeof(partition_table_opt2[0]), + SPI_FLASH_SIZE_MAP_OPT2)) + { + os_printf("system_partition_table_regist 2 success!!\r\n"); + } + else if(system_partition_table_regist( + partition_table_opt4, + sizeof(partition_table_opt4) / sizeof(partition_table_opt4[0]), + SPI_FLASH_SIZE_MAP_OPT4)) + { + os_printf("system_partition_table_regist 4 success!!\r\n"); + } + else if(system_partition_table_regist( + partition_table_opt3, + sizeof(partition_table_opt3) / sizeof(partition_table_opt3[0]), + SPI_FLASH_SIZE_MAP_OPT3)) + { + os_printf("system_partition_table_regist 3 success!!\r\n"); + } + else + { + os_printf("system_partition_table_regist all fail\r\n"); + while(1); + } +} + 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 diff --git a/embedded8266/web/page.mpfs b/embedded8266/web/page.mpfs index 248e4c7..1af97fb 100644 Binary files a/embedded8266/web/page.mpfs and b/embedded8266/web/page.mpfs differ diff --git a/embeddedstm32f303/lib/systems.h b/embeddedstm32f303/lib/systems.h index b193564..274c43e 100644 --- a/embeddedstm32f303/lib/systems.h +++ b/embeddedstm32f303/lib/systems.h @@ -3,6 +3,7 @@ void send_openocd_command(int command, void *message); void send_text( const char * text ); +void send_text_value( const char * text, uint32_t val ); void _delay_us(uint32_t us); diff --git a/embeddedstm32f303/stm32f30x_it.c b/embeddedstm32f303/stm32f30x_it.c index f9f68c8..c5a9f0b 100644 --- a/embeddedstm32f303/stm32f30x_it.c +++ b/embeddedstm32f303/stm32f30x_it.c @@ -140,7 +140,7 @@ void PendSV_Handler(void) */ void SysTick_Handler(void) { - TimingDelay_Decrement(); + TimingDelay_Decrement(); } /******************************************************************************/