diff --git a/colorchord2/DisplayHIDAPI.c b/colorchord2/DisplayHIDAPI.c index 5e4dd70..23d94a0 100644 --- a/colorchord2/DisplayHIDAPI.c +++ b/colorchord2/DisplayHIDAPI.c @@ -27,6 +27,7 @@ struct HIDAPIOutDriver int is_rgby; int bank_size[4]; int bank_id[4]; + int do_write_method; }; @@ -49,13 +50,74 @@ static void * LEDOutThread( void * v ) } printf( "\n" ); */ - int r = hid_send_feature_report( led->devh, led->last_leds, total_bytes ); - if( r < 0 ) + if( led->do_write_method ) { - led->did_init = 0; - printf( "Fault sending LEDs.\n" ); + static int rk; + + int panel = 0; + for( panel = 0; panel < 9; panel++ ) + { + uint8_t hidbuf[66]; + memset( hidbuf, 0x00, 65 ); + hidbuf[0] = panel; + int i; + int tled = panel; + + if( led->do_write_method == 2 ) + { + for( i = 0; i < 16; i++ ) + { + int wled = i * 3; + tled = panel * 16 + i; + hidbuf[wled+2] = OutLEDs[tled*3+1]; + hidbuf[wled+3] = OutLEDs[tled*3+0]; + hidbuf[wled+4] = OutLEDs[tled*3+2]; + } + } + else + { + for( i = 0; i < 16; i++ ) + { + int wled = i * 3; + hidbuf[wled+2] = OutLEDs[tled*3+1]; + hidbuf[wled+3] = OutLEDs[tled*3+0]; + hidbuf[wled+4] = OutLEDs[tled*3+2]; + } + } + + rk += 0x80; + hidbuf[0] = 0; + hidbuf[1] = panel; + + int r; +#if 0 + for( i = 0; i < 64; i++ ) + { + printf( "%02x ", hidbuf[i] ); + } + printf( "\n" ); fflush( stdout ); +#endif +// printf( "." ); fflush( stdout ); + r = hid_write( led->devh, hidbuf, 64 ); + //usleep(1000); + if( r < 0 ) + { + led->did_init = 0; + printf( "Fault sending LEDs.\n" ); + } + } + } + else + { + int r = hid_send_feature_report( led->devh, led->last_leds, total_bytes ); + if( r < 0 ) + { + led->did_init = 0; + printf( "Fault sending LEDs.\n" ); + } } led->readyFlag = 0; + printf( "." ); fflush( stdout ); } OGUSleep(100); } @@ -72,8 +134,17 @@ static void LEDUpdate(void * id, struct NoteFinder*nf) { led->did_init = 1; hid_init(); - - led->devh = hid_open( 0xabcd, 0xf104, 0 ); + + if( led->do_write_method ) + { + //Impulse + led->devh = hid_open( 0x0483, 0x5750, 0 ); + } + else + { + //My dingus. + led->devh = hid_open( 0xabcd, 0xf104, 0 ); + } if( !led->devh ) { @@ -217,6 +288,7 @@ static void LEDParams(void * id ) led->bank_id[1] = 0; RegisterValue( "bank2_id", PAINT, &led->bank_id[1], sizeof( led->bank_id[1] ) ); led->bank_id[2] = 0; RegisterValue( "bank3_id", PAINT, &led->bank_id[2], sizeof( led->bank_id[2] ) ); led->bank_id[3] = 0; RegisterValue( "bank4_id", PAINT, &led->bank_id[3], sizeof( led->bank_id[3] ) ); + led->do_write_method = 0; RegisterValue( "do_write_method", PAINT, &led->do_write_method, sizeof( led->do_write_method ) ); led->did_init = 0; } diff --git a/colorchord2/colorchord.exe b/colorchord2/colorchord.exe old mode 100644 new mode 100755 index 7afcc43..f773c09 Binary files a/colorchord2/colorchord.exe and b/colorchord2/colorchord.exe differ diff --git a/colorchord2/impulse.conf b/colorchord2/impulse.conf new file mode 100644 index 0000000..a6d989b --- /dev/null +++ b/colorchord2/impulse.conf @@ -0,0 +1,37 @@ + +This is a vornoi thing: +outdrivers = DisplayArray, OutputCells, DisplayHIDAPI +lightx = 12 +lighty = 12 +leds = 144 +fromsides = 0 +shape_cutoff = 0.00 +satamp = 5.000 +amppow = 2.510 +distpow = 1.500 + +light_siding = 1.9 + +samplerate = 11025 +buffer = 64 + +#sourcename = default +sourcename = alsa_output.pci-0000_00_1f.3.analog-stereo.monitor + #default +do_write_method = 2 + +amplify = 2.5 +note_attach_amp_iir = 0.9000 +note_attach_amp_iir2 = 0.550 +note_attach_freq_iir = 0.9000 +dft_iir = .6 +dft_q = 20.0000 +dft_speedup = 1000.0000 +note_jumpability = 1.0000 + +#skittlequantity = 24 +timebased = 1 +snakey=0 +qtyamp = 160 + + diff --git a/embedded8266/README.md b/embedded8266/README.md index 90fbc65..6ff06ba 100644 --- a/embedded8266/README.md +++ b/embedded8266/README.md @@ -18,6 +18,11 @@ Unfortunately the I2S Out (WS2812 in) pin is the same as RX1 (pin 25), which mea The audio data is taken from TOUT, but must be kept between 0 and 1V. +An option that has been thurroughly tested is for use with the 2019 MAGFest Swadge. https://github.com/cnlohr/swadge2019 + +Audio portion: +![Audio portion of schematic](https://raw.githubusercontent.com/cnlohr/swadge2019/master/hardware/swadge2019_schematic_audio.png) + ## Notes ./makeconf.inc has a few variables that Make uses for building and flashing the firmware. diff --git a/embedded8266/ccconfig.h b/embedded8266/ccconfig.h index b32d2a6..dc549a7 100644 --- a/embedded8266/ccconfig.h +++ b/embedded8266/ccconfig.h @@ -6,9 +6,9 @@ #define HPABUFFSIZE 512 #define CCEMBEDDED -#define NUM_LIN_LEDS 541 +#define NUM_LIN_LEDS 16 #define DFREQ 16000 - +#define LUXETRON 0 #define memcpy ets_memcpy #define memset ets_memset diff --git a/embedded8266/user/ws2812_i2s.c b/embedded8266/user/ws2812_i2s.c index fb41186..9d00c4f 100644 --- a/embedded8266/user/ws2812_i2s.c +++ b/embedded8266/user/ws2812_i2s.c @@ -34,7 +34,7 @@ Extra copyright info: *******************************************************************************/ - +#include #include "slc_register.h" #include "esp82xxutil.h" #include @@ -45,9 +45,8 @@ 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 +#if LUXETRON == 1 #define INVERT #define WS_I2S_BCK 14 #define WS_I2S_DIV 5 @@ -456,10 +455,10 @@ 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, + 0b0111011101110111, 0b0111011101110011, 0b0111011100110111, 0b0111011100110011, + 0b0111001101110111, 0b0111001101110011, 0b0111001100110111, 0b0111001100110011, + 0b0011011101110111, 0b0011011101110011, 0b0011011100110111, 0b0011011100110011, + 0b0011001101110111, 0b0011001101110011, 0b0011000100110111, 0b0011001100110011, }; #else //Tricky, send out WS2812 bits with coded pulses, one nibble, then the other. diff --git a/embeddedcommon/DFT32.c b/embeddedcommon/DFT32.c index 21df4dd..e08cc78 100644 --- a/embeddedcommon/DFT32.c +++ b/embeddedcommon/DFT32.c @@ -87,10 +87,10 @@ int main() -uint16_t Sdatspace32A[FIXBINS*2]; //(advances,places) +uint16_t Sdatspace32A[FIXBINS*2]; //(advances,places) full revolution is 256. 8bits integer part 8bit fractional int32_t Sdatspace32B[FIXBINS*2]; //(isses,icses) -//This is updated every time the DFT hits the octavecount, or 1/32 updates. +//This is updated every time the DFT hits the octavecount, or 1 out of (1<>16; - int16_t ispc = *(ipt++)>>16; - + int32_t isps = *(ipt++); //keep 32 bits + int32_t ispc = *(ipt++); + // take absolute values + isps = isps<0? -isps : isps; + ispc = ispc<0? -ispc : ispc; int octave = i / FIXBPERO; //If we are running DFT32 on regular ColorChord, then we will need to //also update goutbins[]... But if we're on embedded systems, we only //update embeddedbins32. #ifndef CCEMBEDDED - uint32_t mux = ( (isps) * (isps)) + ((ispc) * (ispc)); - goutbins[i] = sqrtf( (float)mux ); - //reasonable (but arbitrary amplification) + // convert 32 bit precision isps and ispc to floating point + float mux = ( (float)isps * (float)isps) + ((float)ispc * (float)ispc); + goutbins[i] = sqrtf(mux)/65536.0; // scale by 2^16 + //reasonable (but arbitrary attenuation) goutbins[i] /= (78<ispc? isps + (ispc>>1) : ispc + (isps>>1); + rmux = rmux>>16; // keep most significant 16 bits +#else + // use the most significant 16 bits of isps and ispc when squaring + // since isps and ispc are non-negative right bit shifing is well defined + uint32_t rmux = ( (isps>>16) * (isps>>16)) + ((ispc>16) * (ispc>>16)); + rmux = SquareRootRounded( rmux ); +#endif //bump up all outputs here, so when we nerf it by bit shifting by - //ctave we don't lose a lot of detail. - rmux = SquareRootRounded( rmux ) << 1; + //octave we don't lose a lot of detail. + rmux = rmux << 1; embeddedbins32[i] = rmux >> octave; } @@ -194,16 +210,24 @@ static void HandleInt( int16_t sample ) int i; uint16_t adv; uint8_t localipl; + int16_t filteredsample; uint8_t oct = Sdo_this_octave[Swhichoctaveplace]; Swhichoctaveplace ++; Swhichoctaveplace &= BINCYCLE-1; + for( i = 0; i < OCTAVES;i++ ) + { + Saccum_octavebins[i] += sample; + } + if( oct > 128 ) { //Special: This is when we can update everything. - //This gets run one out of every 1/(1<>(OCTAVES-oct); + filteredsample = Saccum_octavebins[oct]>>(OCTAVES-oct); Saccum_octavebins[oct] = 0; for( i = 0; i < FIXBPERO; i++ ) @@ -239,10 +258,10 @@ static void HandleInt( int16_t sample ) localipl = *(dsA) >> 8; *(dsA++) += adv; - *(dsB++) += (Ssinonlytable[localipl] * sample); + *(dsB++) += (Ssinonlytable[localipl] * filteredsample); //Get the cosine (1/4 wavelength out-of-phase with sin) localipl += 64; - *(dsB++) += (Ssinonlytable[localipl] * sample); + *(dsB++) += (Ssinonlytable[localipl] * filteredsample); } } @@ -252,11 +271,12 @@ int SetupDFTProgressive32() int j; Sdonefirstrun = 1; - - for( i = 0; i < BINCYCLE; i++ ) + Sdo_this_octave[0] = 0xff; + for( i = 0; i < BINCYCLE-1; i++ ) { // Sdo_this_octave = - // 4 3 4 2 4 3 4 ... + // 255 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4 is case for 5 octaves. + // Initial state is special one, then at step i do octave = Sdo_this_octave with averaged samples from last update of that octave //search for "first" zero for( j = 0; j <= OCTAVES; j++ ) @@ -271,7 +291,7 @@ int SetupDFTProgressive32() #endif return -1; } - Sdo_this_octave[i] = OCTAVES-j-1; + Sdo_this_octave[i+1] = OCTAVES-j-1; } return 0; } @@ -280,10 +300,12 @@ int SetupDFTProgressive32() void UpdateBins32( const uint16_t * frequencies ) { - int i; - for( i = 0; i < FIXBINS; i++ ) + int i; + int imod = 0; + for( i = 0; i < FIXBINS; i++, imod++ ) { - uint16_t freq = frequencies[i%FIXBPERO]; + if (imod >= FIXBPERO) imod=0; + uint16_t freq = frequencies[imod]; Sdatspace32A[i*2] = freq;// / oneoveroctave; } } diff --git a/embeddedcommon/DFT32.h b/embeddedcommon/DFT32.h index ee5b6cd..31fa18d 100644 --- a/embeddedcommon/DFT32.h +++ b/embeddedcommon/DFT32.h @@ -20,6 +20,13 @@ //made here should be backported there as well. //You can # define these to be other things elsewhere. + +// Will used simple approximation of norm rather than +// sum squares and approx sqrt +#ifndef APPROXNORM +#define APPROXNORM 1 +#endif + #ifndef OCTAVES #define OCTAVES 5 #endif diff --git a/embeddedcommon/embeddedout.c b/embeddedcommon/embeddedout.c index 12a3cf1..0a60dee 100644 --- a/embeddedcommon/embeddedout.c +++ b/embeddedcommon/embeddedout.c @@ -61,17 +61,17 @@ void UpdateLinearLEDs() { if( note_peak_freqs[ sorted_note_map[j] ] > nff ) { - break; + break; // so j is correct place to insert } } - for( k = sorted_map_count; k > j; k-- ) + for( k = sorted_map_count; k > j; k-- ) // make room { sorted_note_map[k] = sorted_note_map[k-1]; } - sorted_note_map[j] = i; + sorted_note_map[j] = i; // insert in correct place #else + sorted_note_map[sorted_map_count] = i; // insert at end #endif - sorted_note_map[sorted_map_count] = i; sorted_map_count++; }