Lab_interaccio/2014/Cuso/Cuso_led_master2/Cuso_led_master2.ino
2025-02-25 21:29:42 +01:00

537 lines
21 KiB
C++

#include "Adafruit_NeoPixel.h"
const uint32_t light_line[16][6] = { { 0, 0, 4095, 4095, 0, 0},
{ 0, 0, 4095, 4095, 0, 0},
{ 0, 0, 4095, 4095, 0, 0},
{4095, 4095, 0, 0, 4095, 4095},
{4095, 4095, 0, 0, 4095, 4095},
{ 0, 0, 4095, 4095, 0, 0},
{ 0, 0, 4095, 4095, 0, 0},
{ 0, 0, 4095, 4095, 0, 0},
{4095, 4095, 0, 0, 4095, 4095},
{4095, 4095, 0, 0, 4095, 4095},
{ 0, 0, 0x005F00AF, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0},
{ 0, 0, 0x00AF6F00, 0, 0, 0},
{ 0, 0, 0x005F00AF, 0, 0, 0},//0x00FF0030,
{ 0, 0, 0, 0, 0, 0},
{ 0, 0, 0x00AF6F00, 0, 0, 0}};//0x00FF5F00
const uint32_t time_line[16][6] = { { 0, 8300, 10000, 12000, 14000, 24000},
{ 0, 10000, 11300, 13800, 15000, 24000},
{ 0, 13200, 15000, 16000, 17500, 24000},
{ 0, 6500, 8500, 16000, 17300, 24000},
{ 0, 1000, 3000, 17500, 18900, 24000},
{ 0, 6000, 7800, 11200, 13000, 24000},
{ 0, 10000, 11800, 15000, 17000, 24000},
{ 0, 14200, 17200, 19000, 20600, 24000},
{ 0, 5200, 7000, 21000, 23000, 24000},
{ 0, 3000, 5000, 22500, 24000, 24000},
{ 0, 6200, 7900, 9100, 13000, 24000},
{ 0, 0, 0, 0, 0, 0},
{ 0, 15000, 16500, 17900, 24000, 24000},
{ 0, 3800, 6000, 7300, 16500, 24000},
{ 0, 0, 0, 0, 0, 0},
{ 0, 19500, 20500, 22500, 24000, 24000}};
//const uint32_t time_line[16][6] = { { 0, 8300, 10000, 12000, 14000, 24000},
// { 0, 10000, 11300, 13800, 15000, 24000},
// { 0, 13200, 15000, 16000, 17500, 24000},
// { 0, 6500, 8500, 16000, 17300, 24000},
// { 0, 2000, 3000, 18000, 18600, 24000},
//
// { 0, 6000, 7800, 11200, 13000, 24000},
// { 0, 10000, 11800, 15000, 17000, 24000},
// { 0, 14200, 17200, 19000, 20600, 24000},
// { 0, 5200, 7000, 21000, 23000, 24000},
// { 0, 3000, 4200, 22800, 24000, 24000},
//
// { 0, 6200, 7900, 9100, 13000, 24000},
// { 0, 0, 0, 0, 0, 0},
// { 0, 15000, 16700, 17500, 18900, 24000},
// { 0, 0, 1000, 2000, 16500, 24000},
// { 0, 0, 0, 0, 0, 0},
// { 0, 19500, 21500, 23500, 24000, 24000}};
static uint32_t time_canal[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
//TLC5940NT pin definitions
#define SIN MOSI // MOSI - Hardware SPI, can't be changed
#define SCLK SCK // SCK - Hardware SPI, can't be changed
#define VPRG 2
#define XLAT 4
#define BLANK 5
#define DCPRG 6
#define GSCLK 7
#define CTS 3
#define PIN 8
#define NUM_LEDS 36
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);
int level[16] = {
4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095 };
const int remap[10] = {
1,2,3,4,5,6,7,8,9,10};
char spi_transfer(volatile byte data)
{
SPDR = data; // Start the transmission
while (!(SPSR & (1<<SPIF))) // Wait the end of the transmission
{
};
return SPDR; // return the received byte
}
void makemagic(){
setGreys();
feedPorts();
}
void feedPorts() {
// Clock for TLC5940's PWM
PORTC |= B01000000; //digitalWrite(BLANK, HIGH);
delayMicroseconds(10);
PORTC &= B10111111; // digitalWrite(BLANK, LOW); //=all outputs ON, start PWM cycle
for (int i=0; i<4096; i++) {
PORTE |= 0x40 ; // bring pin 6 high, but don't touch any of the other pins in PORTE
//16 nanosecs is the min pulse width for the 5940, but no pause seems needed here
PORTE &= 0xBF; // bring pin 6 low without touching the other pins in PORTE
}
}
void setGreys() {
PORTC |= B01000000; //digitalWrite(BLANK, HIGH);
// digitalWrite(XLAT,LOW);
for(int i = 7; i>=0; i--){
spi_transfer( ((long)level[2*i+1] & 0x0FF0) >> 4 );
spi_transfer( (((long)level[2*i+1] & 0xF) << 4) | (((long)level[2*i] & 0x0F00) >> 8) );
spi_transfer( (long)level[2*i] & 0xFF);
}
PORTD |= B00010000; //digitalWrite(XLAT,HIGH);
PORTD &= B11101111; //digitalWrite(XLAT,LOW);
PORTC &= B10111111; // digitalWrite(BLANK, LOW);
}
void startup(){
//Setup the Hardware SPI registers
// SPCR = 01010000
//interrupt disabled,spi enabled,msb 1st,master,clk low when idle,
//sample on leading edge of clk,system clock/4 (fastest)
byte clr;
SPCR = (1<<SPE)|(1<<MSTR);
// clr=SPSR;
// clr=SPDR;
delay(100);
for(byte x = 0; x < 12; ++x){
level[x] = 0;
makemagic();
}
strip.begin(); // Initialization of led matrix
for(int x = 0; x < NUM_LEDS; ++x) strip.setPixelColor(x, 0, 0, 0);
strip.show();
}
//const uint32_t factor = 60;
const uint32_t factor = 30;
uint32_t tiempo_ciclo = 0;
void setup()
{
// Open serial communications and wait for port to open:
pinMode(CTS, OUTPUT);
digitalWrite(CTS, HIGH);
pinMode(MOSI, OUTPUT);
pinMode(SCK, OUTPUT);
pinMode(VPRG, OUTPUT);
pinMode(XLAT, OUTPUT);
pinMode(BLANK, OUTPUT);
pinMode(DCPRG, OUTPUT);
pinMode(GSCLK, OUTPUT);
pinMode(MISO, INPUT);
pinMode(SS,OUTPUT);
digitalWrite(SS,HIGH); //disable device
digitalWrite(MOSI, LOW);
digitalWrite(SCK, LOW);
digitalWrite(XLAT, LOW);
digitalWrite(VPRG, LOW);
digitalWrite(BLANK, HIGH);
digitalWrite(GSCLK, HIGH);
digitalWrite(DCPRG, LOW); // USE EEPROM DC register if LOW
Serial.begin(115200);
// set the data rate for the SoftwareSerial port
Serial1.begin(57600);
startup();
delay(2000);
for (int i=0; i<10;i++) level[remap[i]] = light_line[i][0];
setGreys();
tiempo_ciclo = 24000*factor;
timer1Initialize();
}
void loop() // run over and over
{
refresh();
}
volatile uint32_t time_millis = 0;
const int time_resolution = 100;
static int temp_time_resolution = time_resolution;
float pasoR[6] = { 0, 0, 0, 0, 0, 0};
float pasoG[6] = { 0, 0, 0, 0, 0, 0};
float pasoB[6] = { 0, 0, 0, 0, 0, 0};
float red[6] = { 0, 0, 0, 0, 0, 0};
float green[6] = { 0, 0, 0, 0, 0, 0};
float blue[6] = { 0, 0, 0, 0, 0, 0};
static uint32_t levelRGB = 0;
static int temp_levelref = 0;
static float paso[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static float correc = 1;
const byte quantity = 6;
boolean ok_relampago = true;
boolean refresh_strip = false;
byte temp_red = 0;
byte temp_green = 0;
byte temp_blue = 0;
void refresh()
{
if ((time_millis) >= tiempo_ciclo)
{
for (int canal=0; canal<10;canal++)
{
level[remap[canal]] = light_line[canal][0];
time_canal[canal] = 0;
}
for (int canal=10; canal<16; canal++)
{
time_canal[canal] = 0;
levelRGB = light_line[canal][0];
int red = (0x000000FF&(levelRGB>>16));
int green = (0x000000FF&(levelRGB>>8));
int blue = (0x000000FF&(levelRGB));
for (int num=0; num<quantity; num++) strip.setPixelColor((canal - 10)*quantity + num, red, green, blue);
}
for (int canal=0; canal<6;canal++)
{
pasoR[canal] = 0;
pasoG[canal] = 0;
pasoB[canal] = 0;
}
ok_relampago = true;
strip.show();
setGreys();
timer1Stop();
time_millis = 0;
timer1Initialize();
}
relampago(19000);
//relampago(0);
for (int i=0; i<16; i++)
{
// feedPorts();
if (refresh_strip)
{
strip.show();
refresh_strip = false;
}
for (int j=0; j<6; j++)
{
if (time_millis<=(time_line[i][j]*factor))
{
// Serial.println(time_millis);
if (i>10) temp_time_resolution = time_resolution;
else temp_time_resolution = time_resolution;
if ((time_millis - time_canal[i])>=temp_time_resolution)
{
correc = (time_millis - time_canal[i])/temp_time_resolution;
time_canal[i] = time_millis;
if (i<10)
{
if (j>0) paso[i] = (((float)((int)light_line[i][j] - (int)light_line[i][j - 1]))/((time_line[i][j] - time_line[i][j - 1])*factor)*temp_time_resolution*correc) + paso[i];
else paso[i] = 0;
if ((paso[i]>=1)||(paso[i]<=-1))
{
temp_levelref = level[remap[i]] + paso[i];
if (temp_levelref<0) level[remap[i]] = 0;
else if (temp_levelref>4095) level[remap[i]] = 4095;
else level[remap[i]] = temp_levelref;
setGreys();
paso[i]=0;
}
}
else
{
if ((light_line[i][j]!=light_line[i][j - 1])&&(j>0))
{
byte temp_i = i-10;
if (j>0)
{
temp_red = (0x000000FF&(light_line[i][j]>>16));
temp_green = (0x000000FF&(light_line[i][j]>>8));
temp_blue = 0x000000FF&(light_line[i][j]);
byte temp_red_ant = (0x000000FF&(light_line[i][j-1]>>16));
byte temp_green_ant = (0x000000FF&(light_line[i][j-1]>>8));
byte temp_blue_ant = 0x000000FF&(light_line[i][j-1]);
pasoR[temp_i] = (((float)((int)temp_red - (int)temp_red_ant))/((time_line[i][j]- time_line[i][j - 1])*factor))*temp_time_resolution*correc;
pasoG[temp_i] = (((float)((int)temp_green - (int)temp_green_ant))/((time_line[i][j] - time_line[i][j - 1])*factor))*temp_time_resolution*correc;
pasoB[temp_i] = (((float)((int)temp_blue - (int)temp_blue_ant))/((time_line[i][j] - time_line[i][j - 1])*factor))*temp_time_resolution*correc;
// if (temp_i==3) {Serial.print(pasoR[temp_i]); Serial.print(' '); Serial.print(pasoG[temp_i]); Serial.print(' '); Serial.print(pasoB[temp_i]);}
red[temp_i]= red[temp_i] + pasoR[temp_i];
green[temp_i] = green[temp_i] + pasoG[temp_i];
blue[temp_i] = blue[temp_i] + pasoB[temp_i];
if (red[temp_i] < 0) red[temp_i] = 0;
else if ((red[temp_i] > temp_red)&&(pasoR[temp_i]>0)) red[temp_i] = temp_red;
if (green[temp_i] < 0) green[temp_i] = 0;
else if ((green[temp_i] > temp_green)&&(pasoG[temp_i]>0)) green[temp_i] = temp_green;
if (blue[temp_i] < 0) blue[temp_i] = 0;
else if ((blue[temp_i] > temp_blue)&&(pasoB[temp_i]>0)) blue[temp_i] = temp_blue;
uint32_t temp_color = strip.getPixelColor((temp_i)*quantity);
if (((0x000000FF&(temp_color>>16))!=(byte)red[temp_i])||((0x000000FF&(temp_color>>8))!=(byte)green[temp_i])||((0x000000FF&(temp_color))!=(byte)blue[temp_i]))
{
// if (temp_i==3) {Serial.print(' '); Serial.print((byte)red[temp_i]); Serial.print(' '); Serial.print((byte)green[temp_i]); Serial.print(' '); Serial.println((byte)blue[temp_i]);}
for (int num=0; num<quantity; num++) strip.setPixelColor((temp_i)*quantity + num, (byte)red[temp_i], (byte)green[temp_i], (byte)blue[temp_i]);
refresh_strip = true;
}
}
}
}
}
break;
}
}
}
}
long temp_level[12] = {
4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095};
const char audio = '5';
const float attenua = 4;
boolean stop_millis = false;
void relampago(uint32_t time)
{
if ((time_millis>=time*factor)&&(ok_relampago))
{
stop_millis = true;
ok_relampago = false;
// for (int canal=0; canal<12; canal++) temp_level[canal]=level[remap[canal]];
// for (int canal=0; canal<12; canal++) level[remap[canal]]=0;
setGreys();
for(int x = 0; x < NUM_LEDS; ++x) strip.setPixelColor(x, 0, 0, 0);
strip.show();
delay(10);
// level[remap[3]]=4095;
level[remap[8]]=0;
level[remap[9]]=0;
setGreys();
for (int value=4095; value>4095/attenua; value = value - 4)
{
level[remap[7]]=value;
setGreys();
delayMicroseconds(2000);
}
for (int value=4095; value>200; value = value - 4)
{
level[remap[3]]=value;
level[remap[4]]=value;
level[remap[7]]=value/attenua;
setGreys();
delayMicroseconds(2000);
}
for (int value=200; value>=0; value = value - 4)
{
level[remap[4]]=value;
setGreys();
delayMicroseconds(2000);
}
delay(1000);
while (Serial1.available()) Serial1.read();
boolean flag_ok = true;
int retry = 0;
while ((retry<5)&&(flag_ok))
{
Serial1.print(audio);
delay(100);
unsigned long time_escape = time_millis;
while (!Serial1.available()&&((time_millis-time_escape)<1000));
// while (!Serial1.available());
delay(100);
while (Serial1.available())
{
byte temp = Serial1.read();
Serial.write(temp);
if (temp=='#') flag_ok = false;
}
retry++;
// if (Serial1.read()=='#');
}
while (flag_ok==false)
{
delay(1000);
for(int x = 0; x < NUM_LEDS; ++x) strip.setPixelColor(x, 255, 255, 255);
strip.show();
delay(100);
for(int x = 0; x < NUM_LEDS; ++x) strip.setPixelColor(x, 0, 0, 0);
strip.show();
delay(2000);
for (int value=200; value<4095; value = value + 4)
{
level[remap[3]]=value;
//level[remap[4]]=value;
level[remap[7]]=value/attenua;
setGreys();
delayMicroseconds(3000);
}
delay(14000);
for (int value=4095; value>200; value = value - 4)
{
level[remap[3]]=value;
//level[remap[4]]=value;
level[remap[7]]=value/attenua;
setGreys();
delayMicroseconds(2000);
}
for(int x = 0; x < NUM_LEDS; ++x) strip.setPixelColor(x, 255, 255, 255);
strip.show();
delay(100);
for(int x = 0; x < NUM_LEDS; ++x) strip.setPixelColor(x, 0, 0, 0);
strip.show();
delay(2000);
for (int value=200; value<4095; value = value + 4)
{
level[remap[3]]=value;
level[remap[7]]=value/attenua;
setGreys();
// feedPorts();
delayMicroseconds(2000);
}
// delay(6000);
// int x = random(0, NUM_LEDS);
// int time = random(10, 100);
// strip.setPixelColor(x, 255, 255, 255);
// strip.show();
// delay(time);
// strip.setPixelColor(x, 0, 0, 0);
// strip.show();
// delay(time);
while (!Serial1.available());//feedPorts();;
while (Serial1.available())
{
byte temp = Serial1.read();
if (temp==audio)
{
flag_ok=true;
// digitalWrite(CTS, LOW);
// delay(1000);
// digitalWrite(CTS, HIGH);
}
}
for (int value=0; value<4095; value = value + 2)
{
level[remap[4]]=value;
if (value<(4095/attenua)) level[remap[7]]=4095/attenua;
else level[remap[7]]=value;
setGreys();
// feedPorts();
delayMicroseconds(4000);
}
stop_millis = false;
// if (time_millis>(time_line[7][4]*factor))
// {
// for (int value=4095; value>0; value = value - 4)
// {
// level[remap[7]]=value/attenua;
// setGreys();
// delayMicroseconds(4000);
// }
// float value2=0;
// float pas = 0x5F/255.;
// for (int value=0; value<=255; value = value + 1)
// {
// value2 = value2 + pas;
// for (int num=0; num<quantity; num++) strip.setPixelColor(5*quantity + num, value, value2, 0);
// strip.show();
// delayMicroseconds(10000);
// }
// }
}
//timer1Initialize();
// for (int canal=0; canal<12; canal++) level[remap[canal]] = temp_level[canal];
// setGreys();
}
// Serial.println((millis()-time_total[canal]));
}
const int incr_millis = 10;
#define RESOLUTION 65536 // Timer1 is 16 bit
unsigned int pwmPeriod;
unsigned char clockSelectBits;
char oldSREG; // To hold Status
void timer1SetPeriod(long microseconds) // AR modified for atomic access
{
long cycles = (F_CPU / 2000000) * microseconds; // the counter runs backwards after TOP, interrupt is at BOTTOM so divide microseconds by 2
if(cycles < RESOLUTION) clockSelectBits = _BV(CS10); // no prescale, full xtal
else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11); // prescale by /8
else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11) | _BV(CS10); // prescale by /64
else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12); // prescale by /256
else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12) | _BV(CS10); // prescale by /1024
else cycles = RESOLUTION - 1, clockSelectBits = _BV(CS12) | _BV(CS10); // request was out of bounds, set as maximum
oldSREG = SREG;
cli(); // Disable interrupts for 16 bit register access
ICR1 = pwmPeriod = cycles; // ICR1 is TOP in p & f correct pwm mode
SREG = oldSREG;
TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12));
TCCR1B |= clockSelectBits; // reset clock select register, and starts the clock
}
void timer1Initialize()
{
TCCR1A = 0; // clear control register A
TCCR1B = _BV(WGM13); // set mode 8: phase and frequency correct pwm, stop the timer
timer1SetPeriod(incr_millis*1000);
TIMSK1 = _BV(TOIE1);
}
void timer1Stop()
{
TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12)); // clears all clock selects bits
TIMSK1 &= ~(_BV(TOIE1));
}
//The timer interrupt routine, which periodically interprets the serial commands
ISR(TIMER1_OVF_vect) {
// sei(); //Reenable global interrupts, otherwise serial commands will get dropped
if (!stop_millis) time_millis = time_millis + incr_millis;
feedPorts();
// makemagic();
// makemagic();
// makemagic();
// makemagic();
}