I am on my way with this, but it's going slowly.

This commit is contained in:
cnlohr 2015-06-04 01:51:24 -04:00
parent 202a67326a
commit 518d69c0aa
18 changed files with 998 additions and 0 deletions

View file

@ -0,0 +1,150 @@
#include "colorchord.h"
static uint8_t donefirstrun;
static int8_t sintable[512]; //Actually [sin][cos] pairs.
//LDD instruction on AVR can read with constant offset. We can set Y to be the place in the buffer, and read with offset.
static uint16_t datspace[bins*4]; //(advances,places,isses,icses)
//
void HandleProgressiveInt( int8_t sample1, int8_t sample2 )
{
int i;
uint16_t startpl = 0;
int16_t ts, tc;
int16_t tmp1;
int8_t s1, c1;
uint16_t ipl, localipl, adv;
//startpl maps to 'Y'
//
//Estimated 68 minimum instructions... So for two pairs each... just under 5ksps, theoretical.
//Running overall at ~2kHz.
for( i = 0; i < bins; i++ ) //Loop, fixed size = 3 + 2 cycles 5
{
//12 cycles MIN
adv = datspace[startpl++]; //Read, indirect from RAM (and increment) 2+2 cycles 4
ipl = datspace[startpl++]; //Read, indirect from RAM (and increment) 2+2 cycles 4
//13 cycles MIN
ipl += adv; //Advance, 16bit += 16bit, 1 + 1 cycles 2
localipl = (ipl>>8)<<1; //Select upper 8 bits 1 cycles 1
// need to load Z with 'sintable' and add localipl 2
s1 = sintable[localipl++]; //Read s1 component out of table. 2+2 cycles 2
c1 = sintable[localipl++]; //Read c1 component out of table. 2 cycles 2
ts = (s1 * sample1); // 8 x 8 multiply signed + copy R1 out. zero MSB ts 2
tc = (c1 * sample1); // 8 x 8 multiply signed + copy R1 out. zero MSB tc 2
//15 cycles MIN
ipl += adv; //Advance, 16bit += 16bit, 1 + 1 cycles 2
localipl = (ipl>>8)<<1; //Select upper 8 bits 1 cycles 1
// need to load Z with 'sintable' and add localipl 2
s1 = sintable[localipl++]; //Read s1 component out of table. 2 cycles 2
c1 = sintable[localipl++]; //Read c1 component out of table. 2 cycles 2
ts += (s1 * sample2); // 8 x 8 multiply signed + add R1 out. 3
tc += (c1 * sample2); // 8 x 8 multiply signed + add R1 out. 3
//Add TS and TC to the datspace stuff. (24 instructions)
tmp1 = datspace[startpl]; //Read out, sin component. 4
tmp1 -= tmp1>>6; //Subtract from the MSB (with carry) 2
tmp1 += ts>>6; //Add MSBs with carry 2
datspace[startpl++] = tmp1; //Store values back 4
tmp1 = datspace[startpl]; //Read out, sin component. 4
tmp1 -= tmp1>>6; //Subtract from the MSB (with carry) 2
tmp1 += tc>>6; //Add MSBs with carry 2
datspace[startpl++] = tmp1; //Store values back 4
datspace[startpl-3] = ipl; //Store values back 4
}
}
void SetupConstants()
{
int i;
static int last_place;
if( !donefirstrun )
{
donefirstrun = 1;
for( i = 0; i < 256; i++ )
{
sintable[i*2+0] = i;//(int8_t)((sin( i / 256.0 * 6.283 ) * 127.0));
sintable[i*2+1] = i+1;//(int8_t)((cos( i / 256.0 * 6.283 ) * 127.0));
}
}
for( i = 0; i < bins; i++ )
{
float freq = i;//frequencies[i];
datspace[i*4] = 65536.0/freq;
}
}
/*
void DoDFTProgressiveInteger( float * outbins, float * frequencies, int bins, const float * databuffer, int place_in_data_buffer, int size_of_data_buffer, float q, float speedup )
{
int i;
static int last_place;
if( !donefirstrun )
{
donefirstrun = 1;
for( i = 0; i < 256; i++ )
{
sintable[i*2+0] = (int8_t)((sinf( i / 256.0 * 6.283 ) * 127.0));
sintable[i*2+1] = (int8_t)((cosf( i / 256.0 * 6.283 ) * 127.0));
}
}
if( gbins != bins )
{
gbins = bins;
if( datspace ) free( datspace );
datspace = malloc( bins * 2 * 4 );
}
for( i = 0; i < bins; i++ )
{
float freq = frequencies[i];
datspace[i*4] = 65536.0/freq;
}
for( i = last_place; i != ( place_in_data_buffer&0xffffe ); i = (i+2)%size_of_data_buffer )
{
int8_t ifr1 = (int8_t)( ((databuffer[i+0]) ) * 127 );
int8_t ifr2 = (int8_t)( ((databuffer[i+1]) ) * 127 );
// printf( "%d %d\n", i, place_in_data_buffer&0xffffe );
HandleProgressiveInt( ifr1, ifr2 );
}
last_place = place_in_data_buffer&0xfffe;
//Extract bins.
for( i = 0; i < bins; i++ )
{
int16_t isps = datspace[i*4+2];
int16_t ispc = datspace[i*4+3];
int16_t mux = ( (isps/256) * (isps/256)) + ((ispc/256) * (ispc/256));
// printf( "%d (%d %d)\n", mux, isps, ispc );
outbins[i] = sqrt( mux )/100.0;
}
// printf( "\n");
}
*/

View file

@ -0,0 +1,17 @@
#ifndef _COLORCHORD_H
#define _COLORCHORD_H
#include "mem.h"
#include "c_types.h"
#include "user_interface.h"
#include "ets_sys.h"
#include "osapi.h"
#define bins 120
void HandleProgressiveInt( int8_t sample1, int8_t sample2 );
void SetupConstants();
#endif

View file

@ -0,0 +1,3 @@
#include "mystuff.h"
char generic_print_buffer[384];

View file

@ -0,0 +1,8 @@
#ifndef _MYSTUFF_H
#define _MYSTUFF_H
extern char generic_print_buffer[384];
#define printf( ... ) os_sprintf( generic_print_buffer, __VA_ARGS__ ); uart0_sendStr( generic_print_buffer );
#endif

View file

@ -0,0 +1,143 @@
#include "mem.h"
#include "c_types.h"
#include "user_interface.h"
#include "ets_sys.h"
#include "driver/uart.h"
#include "osapi.h"
#include "espconn.h"
#include "mystuff.h"
#include "ws2812.h"
#define PORT 7777
#define SERVER_TIMEOUT 1000
#define MAX_CONNS 5
#define MAX_FRAME 2000
#define procTaskPrio 0
#define procTaskQueueLen 1
static volatile os_timer_t some_timer;
static struct espconn *pUdpServer;
//Note to self. In future consider looking at this: http://pastebin.com/6eLxSrNz
//Tasks that happen all the time.
os_event_t procTaskQueue[procTaskQueueLen];
static void ICACHE_FLASH_ATTR
procTask(os_event_t *events)
{
system_os_post(procTaskPrio, 0, 0 );
if( events->sig == 0 && events->par == 0 )
{
//Idle Event.
}
}
//Timer event.
static void ICACHE_FLASH_ATTR
myTimer(void *arg)
{
int i;
uart0_sendStr(".");
SetupConstants();
#define GPIO_OUTPUT_SET(gpio_no, bit_value) \
gpio_output_set(bit_value<<gpio_no, ((~bit_value)&0x01)<<gpio_no, 1<<gpio_no,0)
GPIO_OUTPUT_SET(GPIO_ID_PIN(WSGPIO), 0);
WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 1 );
//XXX LOOK HERE!!!
//Right now, I am not actually using real data from the inputs, but rather doing this to test performance of my algorithm.
//The next step is to take real ADC inpts.
for( i = 0; i < 4000; i++ )
{
HandleProgressiveInt( 0xaa, 0xbb );
}
WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 0 );
}
//Called when new packet comes in.
static void ICACHE_FLASH_ATTR
udpserver_recv(void *arg, char *pusrdata, unsigned short len)
{
int i = 0;
struct espconn *pespconn = (struct espconn *)arg;
uint8_t buffer[MAX_FRAME];
//Make sure watchdog is disabled. WS2812's take a while and can mess it up.
ets_wdt_disable();
os_intr_lock();
WS2812OutBuffer( pusrdata, len );
os_intr_unlock();
ets_sprintf( buffer, "%d\r\n", len );
uart0_sendStr(buffer);
}
void ICACHE_FLASH_ATTR at_recvTask()
{
//Called from UART.
}
void user_init(void)
{
uart_init(BIT_RATE_115200, BIT_RATE_115200);
int wifiMode = wifi_get_opmode();
uart0_sendStr("\r\nCustom Server\r\n");
wifi_set_opmode( 2 ); //We broadcast our ESSID, wait for peopel to join.
pUdpServer = (struct espconn *)os_zalloc(sizeof(struct espconn));
ets_memset( pUdpServer, 0, sizeof( struct espconn ) );
espconn_create( pUdpServer );
pUdpServer->type = ESPCONN_UDP;
pUdpServer->proto.udp = (esp_udp *)os_zalloc(sizeof(esp_udp));
pUdpServer->proto.udp->local_port = 7777;
espconn_regist_recvcb(pUdpServer, udpserver_recv);
wifi_station_dhcpc_start();
if( espconn_create( pUdpServer ) )
{
while(1) { uart0_sendStr( "\r\nFAULT\r\n" ); }
}
//XXX TODO figure out how to safely re-allow this.
ets_wdt_disable();
char outbuffer[] = { 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,0xff,0xff, 0x00,0xff,0x00 };
WS2812OutBuffer( outbuffer, 1 ); //Initialize the output.
//Add a process
system_os_task(procTask, procTaskPrio, procTaskQueue, procTaskQueueLen);
uart0_sendStr("\r\nCustom Server\r\n");
WS2812OutBuffer( outbuffer, sizeof(outbuffer) );
//Timer example
os_timer_disarm(&some_timer);
os_timer_setfn(&some_timer, (os_timer_func_t *)myTimer, NULL);
os_timer_arm(&some_timer, 1000, 1);
system_os_post(procTaskPrio, 0, 0 );
}

View file

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

View file

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