Add LED matrix control through USB iso transfers
This commit is contained in:
parent
237d0534fa
commit
f9129b3957
197
colorchord2/DisplayUSBIsochronous.c
Normal file
197
colorchord2/DisplayUSBIsochronous.c
Normal file
|
@ -0,0 +1,197 @@
|
|||
//Copyright 2015 <>< Charles Lohr under the ColorChord License.
|
||||
|
||||
#include "outdrivers.h"
|
||||
#include "notefinder.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "parameters.h"
|
||||
#include <stdlib.h>
|
||||
#include <libusb-1.0/libusb.h>
|
||||
#include "color.h"
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct LEDOutDriver
|
||||
{
|
||||
struct libusb_device_handle *devh;
|
||||
int did_init;
|
||||
int zigzag;
|
||||
int total_leds;
|
||||
int array;
|
||||
float outamp;
|
||||
uint8_t * last_leds;
|
||||
volatile int readyFlag;
|
||||
volatile int transferring;
|
||||
int xn;
|
||||
int yn;
|
||||
int rot90;
|
||||
};
|
||||
|
||||
static void isocb(struct libusb_transfer *tf)
|
||||
{
|
||||
struct LEDOutDriver *led = (struct LEDOutDriver*)tf->user_data;
|
||||
led->transferring = 0;
|
||||
}
|
||||
|
||||
static void * LEDOutThread( void * v )
|
||||
{
|
||||
struct LEDOutDriver * led = (struct LEDOutDriver*)v;
|
||||
|
||||
while(1)
|
||||
{
|
||||
while(!led->readyFlag || !led->did_init || !led->devh) usleep(100);
|
||||
|
||||
int transfers = ((led->total_leds + 19) / 20);
|
||||
int totallength = transfers * 64;
|
||||
|
||||
struct libusb_transfer *tf = libusb_alloc_transfer(transfers);
|
||||
|
||||
tf->dev_handle = led->devh;
|
||||
tf->flags = LIBUSB_TRANSFER_FREE_TRANSFER;
|
||||
tf->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS;
|
||||
tf->num_iso_packets = transfers;
|
||||
libusb_set_iso_packet_lengths(tf, 64);
|
||||
tf->endpoint = 1;
|
||||
tf->flags = 0;
|
||||
tf->buffer = led->last_leds;
|
||||
tf->callback = isocb;
|
||||
tf->length = totallength;
|
||||
tf->user_data = led;
|
||||
|
||||
if(libusb_submit_transfer(tf))
|
||||
{
|
||||
led->did_init = 0;
|
||||
printf( "Fault sending LEDs.\n" );
|
||||
}
|
||||
led->transferring = 1;
|
||||
|
||||
while(led->transferring)
|
||||
{
|
||||
libusb_handle_events(NULL);
|
||||
}
|
||||
led->readyFlag = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void LEDUpdate(void * id, struct NoteFinder*nf)
|
||||
{
|
||||
int i;
|
||||
struct LEDOutDriver * led = (struct LEDOutDriver*)id;
|
||||
|
||||
if( !led->did_init )
|
||||
{
|
||||
led->did_init = 1;
|
||||
if( libusb_init(NULL) < 0 )
|
||||
{
|
||||
fprintf( stderr, "Error: Could not initialize libUSB\n" );
|
||||
// exit( -99 );
|
||||
}
|
||||
|
||||
led->devh = libusb_open_device_with_vid_pid( NULL, 0x16c0, 0x05dc );
|
||||
|
||||
if( !led->devh )
|
||||
{
|
||||
fprintf( stderr, "Error: Cannot find device.\n" );
|
||||
// exit( -98 );
|
||||
}
|
||||
}
|
||||
|
||||
while( led->readyFlag ) usleep(100);
|
||||
|
||||
//Advance the LEDs to this position when outputting the values.
|
||||
for( i = 0; i < led->total_leds; i++ )
|
||||
{
|
||||
int source = i;
|
||||
if( !led->array )
|
||||
{
|
||||
int sx, sy;
|
||||
if( led->rot90 )
|
||||
{
|
||||
sy = i % led->yn;
|
||||
sx = i / led->yn;
|
||||
}
|
||||
else
|
||||
{
|
||||
sx = i % led->xn;
|
||||
sy = i / led->xn;
|
||||
}
|
||||
|
||||
if( led->zigzag )
|
||||
{
|
||||
if( led->rot90 )
|
||||
{
|
||||
if( sx & 1 )
|
||||
{
|
||||
sy = led->yn - sy - 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( sy & 1 )
|
||||
{
|
||||
sx = led->xn - sx - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( led->rot90 )
|
||||
{
|
||||
source = sx + sy * led->xn;
|
||||
}
|
||||
else
|
||||
{
|
||||
source = sx + sy * led->yn;
|
||||
}
|
||||
}
|
||||
|
||||
led->last_leds[i*3+0 + (i / 20 + 1) * 4] = OutLEDs[source*3+1] * led->outamp;
|
||||
led->last_leds[i*3+1 + (i / 20 + 1) * 4] = OutLEDs[source*3+0] * led->outamp;
|
||||
led->last_leds[i*3+2 + (i / 20 + 1) * 4] = OutLEDs[source*3+2] * led->outamp;
|
||||
if(i % 20 == 0)
|
||||
{
|
||||
led->last_leds[(i / 20) * 64 + 0] = i;
|
||||
led->last_leds[(i / 20) * 64 + 1] = i >> 8;
|
||||
led->last_leds[(i / 20) * 64 + 2] = i >> 16;
|
||||
led->last_leds[(i / 20) * 64 + 3] = i >> 24;
|
||||
}
|
||||
}
|
||||
|
||||
led->readyFlag = 1;
|
||||
}
|
||||
|
||||
static void LEDParams(void * id )
|
||||
{
|
||||
struct LEDOutDriver * led = (struct LEDOutDriver*)id;
|
||||
|
||||
led->total_leds = GetParameterI( "leds", 300 );
|
||||
led->last_leds = (uint8_t*)malloc( led->total_leds * 3 + 1 + ((led->total_leds + 19) / 20) * 4 + 64);
|
||||
led->outamp = .1; RegisterValue( "ledoutamp", PAFLOAT, &led->outamp, sizeof( led->outamp ) );
|
||||
led->zigzag = 0; RegisterValue( "zigzag", PAINT, &led->zigzag, sizeof( led->zigzag ) );
|
||||
led->xn = 16; RegisterValue( "lightx", PAINT, &led->xn, sizeof( led->xn ) );
|
||||
led->yn = 9; RegisterValue( "lighty", PAINT, &led->yn, sizeof( led->yn ) );
|
||||
led->rot90 = 0; RegisterValue( "rot90", PAINT, &led->rot90, sizeof( led->rot90 ) );
|
||||
led->array = 0; RegisterValue( "ledarray", PAINT, &led->array, sizeof( led->array ) );
|
||||
|
||||
led->did_init = 0;
|
||||
}
|
||||
|
||||
|
||||
static struct DriverInstances * DisplayUSBIsochronous()
|
||||
{
|
||||
struct DriverInstances * ret = malloc( sizeof( struct DriverInstances ) );
|
||||
memset( ret, 0, sizeof( struct DriverInstances ) );
|
||||
struct LEDOutDriver * led = ret->id = malloc( sizeof( struct LEDOutDriver ) );
|
||||
ret->Func = LEDUpdate;
|
||||
ret->Params = LEDParams;
|
||||
OGCreateThread( LEDOutThread, led );
|
||||
led->readyFlag = 0;
|
||||
LEDParams( led );
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
REGISTER_OUT_DRIVER(DisplayUSBIsochronous);
|
||||
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
all : colorchord colorchord-opengl
|
||||
|
||||
OUTS := OutputVoronoi.o DisplayArray.o OutputLinear.o DisplayPie.o DisplayNetwork.o DisplayUSB2812.o DisplayDMX.o OutputProminent.o RecorderPlugin.o DisplayHIDAPI.o hidapi.o OutputCells.o DisplaySHM.o DisplayFileWrite.o DisplayRadialPoles.o
|
||||
OUTS := OutputVoronoi.o DisplayArray.o OutputLinear.o DisplayPie.o DisplayNetwork.o DisplayUSB2812.o DisplayUSBIsochronous.o DisplayDMX.o OutputProminent.o RecorderPlugin.o DisplayHIDAPI.o hidapi.o OutputCells.o DisplaySHM.o DisplayFileWrite.o DisplayRadialPoles.o
|
||||
|
||||
WINGCC?=i686-w64-mingw32-gcc
|
||||
|
||||
|
|
108
colorchord2/iso.conf
Normal file
108
colorchord2/iso.conf
Normal file
|
@ -0,0 +1,108 @@
|
|||
# This is the configuration file for colorchord.
|
||||
# Most values are already defaulted in the software.
|
||||
# This file is constantly checked for new versions.
|
||||
# \r, and ; are used as terminators, so you can put
|
||||
# multiple entries on the same line.
|
||||
|
||||
#Whether to limit the control loop to ~60ish FPS.
|
||||
cpu_autolimit = 1
|
||||
|
||||
#General GUI properties.
|
||||
title = PA Test
|
||||
#set_screenx = 720
|
||||
#set_screeny = 480
|
||||
|
||||
#Sound properties.
|
||||
buffer = 384
|
||||
play = 0
|
||||
rec = 1
|
||||
channels = 2
|
||||
samplerate = 44100
|
||||
wininput = 1
|
||||
|
||||
#Compiled version will default this.
|
||||
#sound_source = ALSA
|
||||
#-1 indicates left and right, 0 left, 1 right.
|
||||
|
||||
sample_channel = -1
|
||||
sourcename = alsa_output.pci-0000_00_1b.0.analog-stereo.monitor
|
||||
#alsa_output.pci-0000_00_1f.3.analog-stereo.monitor
|
||||
#default
|
||||
# alsa_output.pci-0000_00_1b.0.analog-stereo.monitor
|
||||
#alsa_output.pci-0000_00_1f.3.analog-stereo.monitor << New laptop
|
||||
#use pactl list | grep pci- | grep monitor
|
||||
|
||||
##################################
|
||||
# General ColorChord properties. #
|
||||
##################################
|
||||
|
||||
# How much to amplify the incoming signal.
|
||||
amplify = 5
|
||||
|
||||
# What is the base note? I.e. the lowest note.
|
||||
# Note that it won't have very much impact until an octave up though!
|
||||
base_hz = 55
|
||||
|
||||
# This is only used when dealing with the slow decompose (now defunct)
|
||||
# decompose_iterations = 1000
|
||||
# default_sigma = 1.4000
|
||||
|
||||
# DFT properties for the DFT up top.
|
||||
dft_iir = 0.6
|
||||
dft_q = 20.0000
|
||||
dft_speedup = 1000.0000
|
||||
octaves = 5
|
||||
|
||||
# Should we use a progressive DFT?
|
||||
# 0 = DFT Quick
|
||||
# 1 = DFT Progressive
|
||||
# 2 = DFT Progressive Integer
|
||||
# 3 = DFT Progressive Integer Skippy
|
||||
# 4 = Integer, 32-Bit, Progressive, Skippy.
|
||||
do_progressive_dft = 4fa
|
||||
|
||||
|
||||
filter_iter = 2
|
||||
filter_strength = .5
|
||||
|
||||
# How many bins per octave to use?
|
||||
freqbins = 24
|
||||
|
||||
# For the final note information... How much to slack everything?
|
||||
note_attach_amp_iir = 0.3500
|
||||
note_attach_amp_iir2 = 0.250
|
||||
note_attach_freq_iir = 0.3000
|
||||
|
||||
#How many bins a note can jump from frame to frame to be considered a slide.
|
||||
#this is used to prevent notes from popping in and out a lot.
|
||||
note_combine_distance = 0.5000
|
||||
note_jumpability = 1.8000
|
||||
note_minimum_new_distribution_value = 0.0200
|
||||
note_out_chop = 0.05000
|
||||
|
||||
#compress_coefficient = 4.0
|
||||
#compress_exponent = .5
|
||||
|
||||
|
||||
#=======================================================================
|
||||
#Outputs
|
||||
|
||||
|
||||
outdrivers = DisplayUSBIsochronous, OutputVoronoi, DisplayArray
|
||||
|
||||
leds = 484
|
||||
lightx = 11
|
||||
lighty = 44
|
||||
fromsides = 1
|
||||
shape_cutoff = 0.03
|
||||
satamp = 2.000
|
||||
amppow = 2.5
|
||||
distpow = 1.500
|
||||
zigzag = 1
|
||||
rot90 = 1
|
||||
ledoutamp = .01
|
||||
|
||||
note_attach_amp_iir = .3000
|
||||
note_attach_amp_iir2 = .1500
|
||||
note_attach_freq_iir = 0.3000
|
||||
steady_bright = 0
|
Loading…
Reference in a new issue