/*
* DMX_RGB FADING/FIXED/RAINBOW
*
* Created on: 23/08/2015
* Author:
*/
/*
* SECCION DE INCLUDES
*
*/
// Include para la definicion de las variables
#include <stdint.h>
// Include liberias del micro, Interrupcion / WDT / delay
#include <util\delay.h>
#include <avr/interrupt.h>
//#include <avr/wdt.h>
// Include funcione de DMX
#include "dmx.h"
/*
*
* PROTOTIPOS DE FUNCIONES
*
*
*/
// Funciones de inicializacion de modulos
void vInitPinout(void);
void vInitTimer0(void);
//Funciones Auxiliares
void DimmerCurva(void);
void delay(void);
void Cambiarmodo(void);
// Modos
void fixed_color(void);
void fading_fijo(void);
void fading_auto(void);
void rainbow_fader(void);
/*
*
*
* DEFINICION DE VARIABLES
*
*
*/
enum {FIXED,FADING_FIX,FADING,RAINBOW_FADING} mode,last_mode;
// Dato proveniente de la consola DMX
extern uint8_t DmxRxField[DMX_CHANNELS]; // Valores externos tomados desde la libreria.
#define DMX_R DmxRxField[1] //Canal R
#define DMX_G DmxRxField[2] //Canal G
#define DMX_B DmxRxField[3] //Canal B
#define DMX_Modo DmxRxField[4] //Seleccion de Modo
#define DMX_Velocidad DmxRxField[5] //Seleccion de Velocidad
// Para simplificar los datos del array de colores que estoy usando.
// ArrayColores contiene los valores RGB del momento
#define Rojo ArrayColores[0]
#define Verde ArrayColores[1]
#define Azul ArrayColores[2]
// Definicion de salidas para los colores
#define DDR_PWM DDRB
#define PORT_PWM PORTB
#define PWM_R PB0
#define PWM_G PB1
#define PWM_B PB2
//*********************************//
uint8_t V_out,R_out,A_out; // Valores que se comparan con el PWM
uint8_t V_aux,R_aux,A_aux; // Valores que se cambia para actualizar el PWM
uint8_t PWM_timer=0,Alpha;
uint8_t estado=0,estador=0; // Estado de los fading
const uint8_t arraydimmer[256]={
0, 0, 1, 1, 1, 1, 1, 2,
2, 2, 2, 3, 3, 3, 4, 4,
4, 5, 5, 5, 6, 6, 7, 7,
8, 8, 9, 9, 10, 10, 11, 11,
12, 12, 13, 13, 14, 14, 15, 15,
16, 16, 17, 17, 18, 18, 19, 19,
20, 20, 21, 21, 22, 22, 23, 23,
24, 24, 25, 25, 26, 27, 28, 29,
30, 30, 31, 32, 33, 34, 35, 36,
36, 37, 38, 39, 40, 41, 42, 43,
43, 44, 45, 46, 47, 48, 49, 50,
51, 52, 52, 53, 54, 55, 56, 57,
58, 59, 60, 61, 62, 63, 64, 65,
66, 67, 68, 69, 70, 71, 72, 73,
74, 75, 76, 77, 78, 79, 80, 81,
82, 83, 84, 85, 86, 88, 89, 90,
91, 92, 93, 94, 95, 96, 97, 98,
99, 100, 102, 103, 104, 105, 106, 107,
108, 109, 110, 112, 113, 114, 115, 116,
117, 119, 120, 121, 122, 123, 124, 126,
127, 128, 129, 130, 132, 133, 134, 135,
136, 138, 139, 140, 141, 142, 144, 145,
146, 147, 149, 150, 151, 152, 154, 155,
156, 158, 159, 160, 161, 162, 164, 165,
167, 168, 169, 171, 172, 173, 174, 176,
177, 178, 180, 181, 182, 184, 185, 187,
188, 189, 191, 192, 193, 195, 196, 197,
199, 200, 202, 203, 204, 206, 207, 208,
210, 211, 213, 214, 216, 217, 218, 220,
221, 223, 224, 226, 227, 228, 230, 231,
233, 234, 236, 237, 239, 240, 242, 243,
245, 246, 248, 249, 251, 252, 254, 255
};
uint8_t ArrayColores[3]={255,0,0}; // Rojo,Verde,Azul
const uint8_t ArrayColorFading[6]={ // Indice y valor a modificar {0,1,2} = {R,G,B} ; indice par = incremento ; indice impar = decremento
1, // Rojo -> Amarillo
0, // Amarilo -> Verde
2, // Verde -> Cyan
1, // Cyan -> Azul
0, // Azul -> Magenta
2 // Magenta -> Rojo
};
const uint8_t ArrayColorFadingRainbow[3][2]={ // Indice y valor a modificar {Decremento,Incremento}
{0,1}, // Rojo- -> Verde+
{1,2}, // Verde- -> Azul+
{2,0} // Azul- -> Rojo+
};
/*
*
*
* CODIGOS DE INICIALIZACION DE MODULOS
*
*
*/
//************* Inicialización pines / port *****************//
void vInitPinout(void){
// Configuracion de las llaves DIP para el DMX
// Configuracion de salidas
DDR_PWM |= (1<<PWM_R) | (1<<PWM_G) | (1<<PWM_B); // Salida pin LEDs , PB0 = Rojo, PB1 = Verde, PB2 = Azul
PORT_PWM = 0;
DDRE |= (1<<PE0); // LED indicador de funcionamiento en PE0
PORTE = 0;
}
// ***** inicializacion del timer****//
void vInitTimer0(void){
TCCR0= (1<<CS00) ; // Preescaler 1:1
TIMSK|= (1<<TOIE0); // desbordamientos de la interrupción
}
/*
*
*
* PROGRAMA PRINCIPAL
*
*
*/
int main(void)
{
vInitPinout(); // Establecer los puertos de E / S
vInitTimer0(); // Establecer el timer
vInit_DMX_RX(); // Iniciar la UART y puertos para la llave DIP
last_mode = mode = FIXED; //Valores iniciales, hasta que llegue la trama del DMX
Rojo = 0;
Verde = 0;
Azul = 0;
sei(); // habilitar las interupciones, Timer/UART(DMX) habilitados
while(1) // bucle principal (LOOP)
{
if(!bGetDips()){last_mode=mode=FADING;} // Pregunto si esta activo el DMX y Toma la direccion y la actualiza, tambien desabilita el DMX de ser necesario
if(last_mode!=mode){Cambiarmodo();} // Caso que desde el DMX se pida cambiar el modo, cambia unicamente cuando termino la rutina
switch(last_mode)
{
case FIXED:
fixed_color();
break;
case FADING_FIX:
fading_fijo();
break;
case FADING:
fading_auto();
break;
case RAINBOW_FADING:
rainbow_fader();
break;
default:
break;
}
}
}
/*
*
*
* MODOS DE OPERACION
*
* fixed_color() - Color fijo, tomado desde el DMX.
* fading_fijo() - Produce el efecto de fading con el color tomado del DMX, pero solo ese color, de 0 a 255.
* fading_auto() - Comienza la ejecucion de fading de distintos colores, solo toma en cuenta la velocidad, solo 1 color a la ves.
* rainbow_fading() - Agregado al fading_auto(), en caso que se seleccione este, se modificaran 2 colores en ves de 1.
*/
void fixed_color(void){
Rojo = DMX_R; // Colores tomados directamente del DMX para fijo
Verde = DMX_G;
Azul = DMX_B;
DimmerCurva(); // Actualizo colores para el PWM
}
void fading_fijo(void){
Rojo = DMX_R * (Alpha/255); // Colores tomados directamente del DMX para fijo
Verde = DMX_G * (Alpha/255);
Azul = DMX_B * (Alpha/255);
DimmerCurva();
Alpha++;
delay();
}
void fading_auto(void){
// Valores iniciales seteados cuando se cambia de modo
//Espera
delay(); //esperar
//Cambio los valores, cuando se cambia de modo se procede a setear los valores iniciales
if(estado%2)
{ //Caso impar
if(++ArrayColores[estado]==255) estado++;
}
else
{ //Caso par
if(--ArrayColores[estado]==0) estado++;
}
if(estado>=6) estado=0;
DimmerCurva();
}
void rainbow_fader(void){
int Temp_R,Temp_A,Temp_V;
Temp_R = Rojo;
Temp_A = Azul;
Temp_V = Verde;
if (estador==0){ //Caso inicial, Para que comienze con los valores que debe
Rojo = 255;
Verde = 0;
Azul = 0;
}
DimmerCurva();
ArrayColores[ArrayColorFadingRainbow[estador][1]]++; //Sumo
ArrayColores[ArrayColorFadingRainbow[estador][0]]--; //Resto
if(!ArrayColores[ArrayColorFadingRainbow[estador][0]]) estador++; //Compruebo que llegue al final, es decir pase por los 255 valores, en este caso cuando llega a 0 y continuo con la otra seccion.
Rojo = Temp_R;
Azul = Temp_A;
Verde = Temp_V;
if(estador>=3) estador=0; fading_auto(); //En caso que pase por todos los colores y pasas por el fade comun, tal cual estaba en el otro programa
}
/*
*
*
* UTILIDADES
*
*
* DimmerCurva() - Actualiza los colores para que el PWM tome los valores nuevos
* delay() - Demora introducida para modificar la velocidad de los efectos
* Cambiarmodo() - Funcion usada que toma el valor del DMX, traduciendolo y efectua el cambio.
*/
void DimmerCurva(void){
R_aux=arraydimmer[Rojo];
V_aux=arraydimmer[Verde];
A_aux=arraydimmer[Azul];
}
void delay(void) {
// Se toma el valor actual de la velocidad entregada por el DMX, no hace falta esperar que termine el PWM
// Tiempo Minimo = 3us
// Tiempo Maximo = 580ms
// Dividi el tiempo en 2 partes 0..127 para tiempos de micro segundos y 128..255 para tiempos de milisegundos
uint16_t tiempo;
if (DMX_Velocidad>127)
{ //Tiempo en milisegundos, Recta de 1ms a 508ms
tiempo = 4*DMX_Velocidad - 511;
//_delay_ms(tiempo);
}
else
{ //Tiempo en microsegundos de 3us a 892us, valores elegidos para que resulte mas facil multiplicarlos
tiempo = 7*DMX_Velocidad +3;
//_delay_us(tiempo);
}
}
void Cambiarmodo(void){
last_mode=mode;
switch(mode) // Tomo los 2 bits superiores del Modo que viene del DMX y le hago una AND con 1100 0000, dejando los 2 bits superiores y los demas en 0
{
case RAINBOW_FADING: //Caso RAINBOW_FADING de 192 a 255, los bits con mas pesos siempre se mantienen en 1100
Rojo=255; // Set de colores iniciales
Verde=0;
Azul=0;
estado=0; // Set de estado inicial para el fading
estador=0; // Set de estado inicial para el rainbow_fading
break;
case FADING: //Case FADING, de 128 a 191, bits de mayor peso quedan siempre en 1000
Rojo=255; // Set de colores iniciales
Verde=0;
Azul=0;
estado=0; // Set de estado inicial para el fading
break;
default: //Case FADING_FIX, de 64 a 127, y FIXED, de 0 a 63. Bits de mayor peso quedan siempre en 01 y 00
break;
}
}
void SetMode(void){
switch(DMX_Modo&0xC0) // Tomo los 2 bits superiores del Modo que viene del DMX y le hago una AND con 1100 0000, dejando los 2 bits superiores y los demas en 0
{
case 0xC0: //Caso RAINBOW_FADING de 192 a 255, los bits con mas pesos siempre se mantienen en 1100
mode=RAINBOW_FADING;
break;
case 0x80: //Case FADING, de 128 a 191, bits de mayor peso quedan siempre en 1000
mode=FADING;
break;
case 0x40: //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0100
mode=FADING_FIX; // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
break;
case 0x00: //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0000
mode=FIXED; // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
break;
}
}
/*
*
*
* ESPACIO PARA INTERRUPCIONES
*
*
* Timer0 - Por Overflow - Para el PWM por software
* UART - RX - Para el DMX
*/
void ISR(TIMER0_OVF_vect){
if (!PWM_timer) PORT_PWM |= ((1<<PWM_R)|(1<<PWM_R)|(1<<PWM_R)); // Si es 0 el PWM_timer pone a 1 las salidas
if (R_out>=PWM_timer) { PORT_PWM &= ~(1<<PWM_R); } // Cuando se cumple el tiempo las pone a 0, es decir cuando tenga 255 es el maximo que van a estar encendidas
if (V_out>=PWM_timer) { PORT_PWM &= ~(1<<PWM_G); }
if (A_out>=PWM_timer) { PORT_PWM &= ~(1<<PWM_B); }
if (PWM_timer==255)
{
//Cargo los colores nuevos ya que finalizo el ciclo del PWM
R_out = R_aux;
V_out = V_aux;
A_out = A_aux;
//Observo si se cambio el modo, si cambio el modo cargo el nuevo modo y espero que el programa principal termine lo que estaba haciendo para comenzar con el nuevo modo
SetMode();
}
PWM_timer++;
}
void ISR (UART_RX_vect)
{
vHook_DMX_UART();
}