From 442a5c608bc4cbfa734d0b69d0a334d287e4a03c Mon Sep 17 00:00:00 2001 From: daniel3514 Date: Sat, 1 Aug 2020 18:56:51 -0500 Subject: [PATCH 1/2] update --- DMX_Controller/DMX_Controller.cpp.elf | Bin 0 -> 200243 bytes DMX_Controller/DMX_Controller.cpp.hex | 1713 +++++++ DMX_Controller/DMX_Controller.ino | 6658 +++++++++++++------------ 3 files changed, 5055 insertions(+), 3316 deletions(-) create mode 100644 DMX_Controller/DMX_Controller.cpp.elf create mode 100644 DMX_Controller/DMX_Controller.cpp.hex diff --git a/DMX_Controller/DMX_Controller.cpp.elf b/DMX_Controller/DMX_Controller.cpp.elf new file mode 100644 index 0000000000000000000000000000000000000000..dbada6b84fb22ecaf9d988a43d3b6b94062390fa GIT binary patch literal 200243 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¥$&mWnxEfknGsszq((Wr^wsV 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 cv. ** -// ** ** -// *************************************************************************************************************************** -// *************************************************************************************************************************** - -// Librerias -#include // libreria para LCD -#include -#include -#include -#include // libreria DMX 4 universos deskontrol four universes DMX library - http://www.deskontrol.net/blog - -// DMX Library -#define DMX512 (0) // (250 kbaud - 2 to 512 channels) Standard USITT DMX-512 -//#define DMX1024 (1) // (500 kbaud - 2 to 1024 channels) Completely non standard - TESTED ok -//#define DMX2048 (2) // (1000 kbaud - 2 to 2048 channels) called by manufacturers DMX1000K, DMX 4x or DMX 1M ??? - -// Puertos, variables -// DMX -int DMX_Data_Flux = 2; // control de flujo de datos para dmx, 0 por default -int DMX_Values [515]; // array de valores actuales DMX -int Canal_Actual = 1; -byte Universo_Actual = 0; -// Botones cursor -int Boton_Up = 9; -int Boton_Down = 12; -int Boton_Left = 8; -int Boton_Right = 10; -int Boton_Center = 11; -byte LCD_Col_Pos = 0; // posicion en tiempo real de lcd -byte LCD_Row_Pos = 0; // posicion en tiempo real de lcd -// config de posiciones de lcd Col Row -byte Cursor_Conf[4][20] = { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }; -// Botones Numerico Array -int Boton_Array_1 = 38; -int Boton_Array_2 = 40; -int Boton_Array_3 = 42; -int Boton_Array_4 = 44; -int Boton_Array_A = 30; -int Boton_Array_B = 32; -int Boton_Array_C = 34; -int Boton_Array_D = 36; -byte Boton_Calc = 17; // valor calculado # E * F, 17 sin valor calculado -byte Num_Col_Pos = 0; // posicion en tiempo real de lcd -byte Num_Row_Pos = 0; // posicion en tiempo real de lcd -int Num_Val = 0; // valor generado al calculo -long Boton_Delay_Teclado = 100; // delay de lectura de boton -// Potenciometro -int Pot = A15; // entrada de potenciometro -// LCD -int LCD_RS = 43; // puertos de conexion de LCD -int LCD_E = 45; -int LCD_D4 = 47; -int LCD_D5 = 49; -int LCD_D6 = 51; -int LCD_D7 = 53; -LiquidCrystal lcd(LCD_RS, LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7); //LCD setup -int Back_Light_PWM = 13; // salida para PWM de Back Light de LCD -int Contrast_PWM = 4; // salida para pwm de contraste de LCD -byte Light_On_Off = 0; // saber si esta encendida o apagada, back y key -// Key Light -int Key_Light_PWM = 3; // salida para pwm de key light -// EEPROM -int BackLight_Add = 4094; // direccion de eeprom -int Contrast_Add = 4095; // direccion de eeprom -int Bank_Init_Add = 4093; // direccion de eeprom -int Key_Light_Add = 4092; // direccion de eeprom -int EEPROM_Limit = 4091; // limite de espacios en eeprom para universos - -void setup() -{ - // DMX - // pinMode(DMX_Data_Flux, OUTPUT); - // Botones cursor - pinMode(Boton_Up, INPUT_PULLUP); - pinMode(Boton_Down, INPUT_PULLUP); - pinMode(Boton_Left, INPUT_PULLUP); - pinMode(Boton_Right, INPUT_PULLUP); - pinMode(11, INPUT_PULLUP); //Boton_Center, INPUT_PULLUP); - // Botones numerico - pinMode(Boton_Array_1, OUTPUT); - pinMode(Boton_Array_2, OUTPUT); - pinMode(Boton_Array_3, OUTPUT); - pinMode(Boton_Array_4, OUTPUT); - pinMode(Boton_Array_A, INPUT_PULLUP); - pinMode(Boton_Array_B, INPUT_PULLUP); - pinMode(Boton_Array_C, INPUT_PULLUP); - pinMode(Boton_Array_D, INPUT_PULLUP); - digitalWrite(Boton_Array_1, HIGH); - digitalWrite(Boton_Array_2, HIGH); - digitalWrite(Boton_Array_3, HIGH); - digitalWrite(Boton_Array_4, HIGH); - // LCD - pinMode(LCD_RS, OUTPUT); - pinMode(LCD_E, OUTPUT); - pinMode(LCD_D7, OUTPUT); - pinMode(LCD_D6, OUTPUT); - pinMode(LCD_D5, OUTPUT); - pinMode(LCD_D4, OUTPUT); - pinMode(Back_Light_PWM, OUTPUT); - lcd.begin(20, 4); //tamaño de LCD - // Key Light - pinMode(Key_Light_PWM, OUTPUT); - // DMX - ArduinoDmx0.set_tx_address(1); // poner aqui la direccion de inicio de DMX - ArduinoDmx0.set_tx_channels(512); // poner aqui el numero de canales a transmitir - ArduinoDmx0.init_tx(DMX512); // iniciar transmision universo 0, modo estandar DMX512 - // no conectados - pinMode(5, OUTPUT); - digitalWrite(5, LOW); - pinMode(6, OUTPUT); - digitalWrite(6, LOW); - pinMode(7, OUTPUT); - digitalWrite(7, LOW); - pinMode(22, OUTPUT); - digitalWrite(22, LOW); - pinMode(23, OUTPUT); - digitalWrite(23, LOW); - pinMode(24, OUTPUT); - digitalWrite(24, LOW); - pinMode(25, OUTPUT); - digitalWrite(25, LOW); - pinMode(26, OUTPUT); - digitalWrite(26, LOW); - pinMode(27, OUTPUT); - digitalWrite(27, LOW); - pinMode(28, OUTPUT); - digitalWrite(28, LOW); - pinMode(29, OUTPUT); - digitalWrite(29, LOW); - pinMode(31, OUTPUT); - digitalWrite(31, LOW); - pinMode(33, OUTPUT); - digitalWrite(33, LOW); - pinMode(35, OUTPUT); - digitalWrite(35, LOW); - pinMode(37, OUTPUT); - digitalWrite(37, LOW); - pinMode(39, OUTPUT); - digitalWrite(39, LOW); - pinMode(41, OUTPUT); - digitalWrite(41, LOW); - pinMode(46, OUTPUT); - digitalWrite(46, LOW); - pinMode(48, OUTPUT); - digitalWrite(48, LOW); - pinMode(50, OUTPUT); - digitalWrite(50, LOW); - pinMode(52, OUTPUT); - digitalWrite(52, LOW); - pinMode(A0, OUTPUT); - digitalWrite(A0, LOW); - pinMode(A1, OUTPUT); - digitalWrite(A1, LOW); - pinMode(A2, OUTPUT); - digitalWrite(A2, LOW); - pinMode(A3, OUTPUT); - digitalWrite(A3, LOW); - pinMode(A4, OUTPUT); - digitalWrite(A4, LOW); - pinMode(A5, OUTPUT); - digitalWrite(A5, LOW); - pinMode(A6, OUTPUT); - digitalWrite(A6, LOW); - pinMode(A7, OUTPUT); - digitalWrite(A7, LOW); - pinMode(A8, OUTPUT); - digitalWrite(A8, LOW); - pinMode(A9, OUTPUT); - digitalWrite(A9, LOW); - pinMode(A10, OUTPUT); - digitalWrite(A10, LOW); - pinMode(A11, OUTPUT); - digitalWrite(A11, LOW); - pinMode(A12, OUTPUT); - digitalWrite(A12, LOW); - pinMode(A13, OUTPUT); - digitalWrite(A13, LOW); - pinMode(A14, OUTPUT); - digitalWrite(A14, LOW); -} - -void loop() -{ - digitalWrite(2, HIGH); // max 485 como salida - Back_Light_Init(); - Contrast_Init(); - EEPROM_Load_Init(); - GUI_About(); - GUI_Memory_Init(); -} - -void Back_Light_Init() -{ - // ultimo estado del back light - byte Back_Light_Value = EEPROM.read(BackLight_Add); - analogWrite(Back_Light_PWM, Back_Light_Value); - if (Back_Light_Value == 0) - { - Light_On_Off = 0; - } - if (Back_Light_Value > 0) - { - Light_On_Off = 1; - } -} - -void Key_Light_Init() -{ - // ultimo estado del Key Light - byte Key_Light_Value = EEPROM.read(Key_Light_Add); - analogWrite(Key_Light_PWM, Key_Light_Value); - if (Key_Light_Value == 0) - { - Light_On_Off = 0; - } - if (Key_Light_Value > 0) - { - Light_On_Off = 1; - } -} - -void Contrast_Init() -{ - // ultimo estado del comtrast - byte Contrast_Value = EEPROM.read(Contrast_Add); - if (Contrast_Value < 150) - { - Contrast_Value = 150; - } - analogWrite(Contrast_PWM, Contrast_Value); -} - -void Light_En() -{ - // encender back y key desde la tecla * - byte Back_Light_Value = EEPROM.read(BackLight_Add); // lectura del ultimo valor desde la eeprom - byte Key_Light_Value = EEPROM.read(Key_Light_Add); // lectura del ultimo valor desde la eeprom - long delay_dimmer = 1; - // encender - if (Light_On_Off == 0) // si esta apagada encenderla - { - // si el valor es 0 lo encendemos de todos modos - if (Back_Light_Value == 0) - { - for(int contar = 0; contar <= 127; contar ++) - { - analogWrite(Back_Light_PWM, contar); // aqui el valor a encender en el caso que se haya establecido apagado - delay(delay_dimmer); - } - } - if (Key_Light_Value == 0) - { - for(int contar = 0; contar <= 127; contar ++) - { - analogWrite(Key_Light_PWM, 127); // aqui el valor a encender en el caso que se haya establecido apagado - delay(delay_dimmer); - } - } - // solo encender - if (Back_Light_Value > 0) - { - for(int contar = 0; contar <= Back_Light_Value; contar ++) - { - analogWrite(Back_Light_PWM, contar); // encender con el valor de la eeprom - delay(delay_dimmer); - } - } - if (Key_Light_Value > 0) - { - for(int contar = 0; contar <= Back_Light_Value; contar ++) - { - analogWrite(Key_Light_PWM, Key_Light_Value);// encender con el valor de la eeprom - delay(delay_dimmer); - } - } - Light_On_Off = 1; - goto salida; - } - // apagar - if (Light_On_Off == 1) // si esta encendida apagarla - { - for(int contar = Back_Light_Value; contar != 0; contar --) - { - analogWrite(Back_Light_PWM, contar); - delay(delay_dimmer); - } - analogWrite(Back_Light_PWM, 0); - analogWrite(Key_Light_PWM, 0); - Light_On_Off = 0; - } - salida: - delay(300); // para impedir repeticion del comando -} - -void GUI_Licence() -{ - int retardo = 4000; - lcd.clear (); - lcd.setCursor(0, 0); - lcd.print(" This program is"); - lcd.setCursor(0, 1); - lcd.print("distributed in the"); - lcd.setCursor(0, 2); - lcd.print("hope that it will be"); - lcd.setCursor(0, 3); - lcd.print("useful, but"); - delay(retardo); - - lcd.clear (); - lcd.setCursor(0, 0); - lcd.print("WITHOUT ANY WARRANTY"); - lcd.setCursor(0, 1); - lcd.print("without even the"); - lcd.setCursor(0, 2); - lcd.print("implied warranty of"); - lcd.setCursor(0, 3); - lcd.print("MERCHANTABILITY of"); - delay(retardo); - - lcd.clear (); - lcd.setCursor(0, 0); - lcd.print("FITNESS FOR A"); - lcd.setCursor(0, 1); - lcd.print("PARTICULAR PORPUSE."); - lcd.setCursor(0, 2); - lcd.print(" This is free "); - lcd.setCursor(0, 3); - lcd.print("software and you are"); - delay(retardo); - - lcd.clear (); - lcd.setCursor(0, 0); - lcd.print("welcome to"); - lcd.setCursor(0, 1); - lcd.print("redistribute it"); - lcd.setCursor(0, 2); - lcd.print("under certain"); - lcd.setCursor(0, 3); - lcd.print("conditions"); - delay(retardo); - - lcd.clear (); - lcd.setCursor(0, 0); - lcd.print("See the GNU GENERAL"); - lcd.setCursor(0, 1); - lcd.print("PUBLIC LICENCE"); - lcd.setCursor(0, 2); - lcd.print("for more details..."); - delay(retardo); -} - -void GUI_About() -{ - byte Firm_Ver_Ent = 1; - byte Firm_Ver_Dec = 5; - byte Hard_Ver_Ent = 0; - byte Hard_Ver_Dec = 4; - byte Key_Light_Value = EEPROM.read(Key_Light_Add); - byte Back_Light_Value = EEPROM.read(BackLight_Add); - lcd.clear (); - analogWrite(Key_Light_PWM, 0); - analogWrite(Back_Light_PWM, 0); - for(int numero = 0; numero <= 512; numero ++) // efecto binario en lcd - { - // binario - lcd.print (numero, BIN); - // key light - if(Key_Light_Value > 0) - { - if(numero <= 255) - { - if(numero <= Key_Light_Value) - { - analogWrite(Key_Light_PWM, numero); - } - } - } - // back light - if(Back_Light_Value > 0) - { - if(numero <= 255) - { - if(numero <= Back_Light_Value) - { - analogWrite(Back_Light_PWM, numero); - } - } - } - } - lcd.clear (); - lcd.blink (); - lcd.setCursor(3, 0); - lcd.print("Arduino DMX-512"); - lcd.setCursor(1, 1); - lcd.print("Tester & Controller"); - // Firmware - lcd.setCursor(0, 3); - lcd.print("Firm v"); - lcd.print(Firm_Ver_Ent); - lcd.print("."); - lcd.print(Firm_Ver_Dec); - // Hardware - lcd.setCursor(11, 3); - lcd.print("Hard v"); - lcd.print(Hard_Ver_Ent); - lcd.print("."); - lcd.print(Hard_Ver_Dec); - // bank - lcd.setCursor(9, 2); - lcd.print("b"); - if (Universo_Actual == 0) - { - lcd.print("-"); - } - else - { - lcd.print(Universo_Actual); - } - lcd.setCursor(10, 2); // Blink - // lectura del boton centro - while (digitalRead(Boton_Center) == HIGH) - { - - } - delay (300); // rebote de boton - lcd.clear (); - lcd.setCursor(0, 0); - lcd.print("Open Source License:"); - lcd.setCursor(0, 1); - lcd.print("Firm: GNU GPL v3"); - lcd.setCursor(0, 2); - lcd.print("Hard: OSHW v1"); - lcd.setCursor(0, 3); - lcd.print("Wiki: goo.gl/5nqJKt"); - lcd.setCursor(2, 1); - // bank - lcd.setCursor(18, 1); - lcd.print("b"); - if (Universo_Actual == 0) - { - lcd.print("-"); - } - else - { - lcd.print(Universo_Actual); - } - lcd.setCursor(19, 1); - // lectura del boton centro - while (digitalRead(Boton_Center) == HIGH) - { - - } - delay (300); // rebote de boton - lcd.noBlink (); -} - -void Multi_Matrix(int inicial) -{ - // dibujar banco - Numerico_Write (inicial, 13, 0); - Numerico_Write (inicial + 14, 17, 0); - // matrix 1 - Numerico_Write (DMX_Values[inicial], 1, 1); - Numerico_Write (DMX_Values[inicial + 1], 5, 1); - Numerico_Write (DMX_Values[inicial + 2], 9, 1); - Numerico_Write (DMX_Values[inicial + 3], 13, 1); - Numerico_Write (DMX_Values[inicial + 4], 17, 1); - // matrix 2 - Numerico_Write (DMX_Values[inicial + 5], 1, 2); - Numerico_Write (DMX_Values[inicial + 6], 5, 2); - Numerico_Write (DMX_Values[inicial + 7], 9, 2); - Numerico_Write (DMX_Values[inicial + 8], 13, 2); - Numerico_Write (DMX_Values[inicial + 9], 17, 2); - // matrix 3 - Numerico_Write (DMX_Values[inicial + 10], 1, 3); - Numerico_Write (DMX_Values[inicial + 11], 5, 3); - Numerico_Write (DMX_Values[inicial + 12], 9, 3); - Numerico_Write (DMX_Values[inicial + 13], 13, 3); - Numerico_Write (DMX_Values[inicial + 14], 17, 3); -} - -void GUI_Control_Matrix() -{ - int Inicial = 1; - Canal_Actual = 1; - inicio: - lcd.clear(); - lcd.setCursor (0, 0); - lcd.print("c--- Mb Exi -"); - lcd.setCursor (7, 0); - if (Universo_Actual == 0) - { - lcd.print("-"); - } - else - { - lcd.print(Universo_Actual); - } - Multi_Matrix (Inicial); - // Cursor - LCD_Col_Pos = 12; // posicion de cursor - LCD_Row_Pos = 0; // posicion e cursor - // configuracion de cursor - Cursor_Conf_Clear(); // limpiar array - // Row 0 - Cursor_Conf[0][4] = 1; // Memory - Cursor_Conf[0][8] = 1; // Unit - Cursor_Conf[0][12] = 1; // Banco Inicial - Cursor_Conf[0][16] = 1; // Banco Final - // Row 1 - Cursor_Conf[1][0] = 1; - Cursor_Conf[1][4] = 1; - Cursor_Conf[1][8] = 1; - Cursor_Conf[1][12] = 1; - Cursor_Conf[1][16] = 1; - // Row 2 - Cursor_Conf[2][0] = 1; - Cursor_Conf[2][4] = 1; - Cursor_Conf[2][8] = 1; - Cursor_Conf[2][12] = 1; - Cursor_Conf[2][16] = 1; - // Row 3 - Cursor_Conf[3][0] = 1; - Cursor_Conf[3][4] = 1; - Cursor_Conf[3][8] = 1; - Cursor_Conf[3][12] = 1; - Cursor_Conf[3][16] = 1; - // navegar - Banco: - GUI_Navegar(1, Inicial); - // Acciones - // Memory - if (LCD_Col_Pos == 4 && LCD_Row_Pos == 0) - { - GUI_Memory(); - goto inicio; - } - // Control - if (LCD_Col_Pos == 8 && LCD_Row_Pos == 0) - { - GUI_Control_Options(); - goto inicio; - } - // Banco Inicial - if (LCD_Col_Pos == 12 && LCD_Row_Pos == 0) - { - Num_Row_Pos = 0; - Num_Col_Pos = 13; - Num_Val = Inicial; // para dejar el numero que estaba si no se cambia - Numerico_Calc(0); - if (Num_Val > 498) // limite de matriz - { - Num_Val = 498; - } - if (Num_Val == 0) // limite de matriz - { - Num_Val = 1; - } - Inicial = Num_Val; - goto inicio; - } - // Banco Final - if (LCD_Col_Pos == 16 && LCD_Row_Pos == 0) - { - Num_Row_Pos = 0; - Num_Col_Pos = 17; - if (Inicial == 1) - { - Num_Val = 15; - } - else - { - Num_Val = Inicial - 14; // para dejar el numero que estaba si no se cambia - Numerico_Calc(0); - } - if (Num_Val > 512) // limite de matriz - { - Inicial = 498; - goto inicio; - } - if (Num_Val < 15) // limite de matriz - { - Inicial = 1; - goto inicio; - } - Inicial = Num_Val - 14; - goto inicio; - } - // posicion 1 - if (LCD_Col_Pos == 0 && LCD_Row_Pos == 1) - { - Canal_Actual = Inicial; - goto Salida_DMX; - } - // posicion 2 - if (LCD_Col_Pos == 4 && LCD_Row_Pos == 1) - { - Canal_Actual = Inicial + 1; - goto Salida_DMX; - } - // posicion 3 - if (LCD_Col_Pos == 8 && LCD_Row_Pos == 1) - { - Canal_Actual = Inicial + 2; - goto Salida_DMX; - } - // posicion 4 - if (LCD_Col_Pos == 12 && LCD_Row_Pos == 1) - { - Canal_Actual = Inicial + 3; - goto Salida_DMX; - } - // posicion 5 - if (LCD_Col_Pos == 16 && LCD_Row_Pos == 1) - { - Canal_Actual = Inicial + 4; - goto Salida_DMX; - } - // posicion 6 - if (LCD_Col_Pos == 0 && LCD_Row_Pos == 2) - { - Canal_Actual = Inicial + 5; - goto Salida_DMX; - } - // posicion 7 - if (LCD_Col_Pos == 4 && LCD_Row_Pos == 2) - { - Canal_Actual = Inicial + 6; - goto Salida_DMX; - } - // posicion 8 - if (LCD_Col_Pos == 8 && LCD_Row_Pos == 2) - { - Canal_Actual = Inicial + 7; - goto Salida_DMX; - } - // posicion 9 - if (LCD_Col_Pos == 12 && LCD_Row_Pos == 2) - { - Canal_Actual = Inicial + 8; - goto Salida_DMX; - } - // posicion 10 - if (LCD_Col_Pos == 16 && LCD_Row_Pos == 2) - { - Canal_Actual = Inicial + 9; - goto Salida_DMX; - } - // posicion 11 - if (LCD_Col_Pos == 0 && LCD_Row_Pos == 3) - { - Canal_Actual = Inicial + 10; - goto Salida_DMX; - } - // posicion 12 - if (LCD_Col_Pos == 4 && LCD_Row_Pos == 3) - { - Canal_Actual = Inicial + 11; - goto Salida_DMX; - } - // posicion 13 - if (LCD_Col_Pos == 8 && LCD_Row_Pos == 3) - { - Canal_Actual = Inicial + 12; - goto Salida_DMX; - } - // posicion 14 - if (LCD_Col_Pos == 12 && LCD_Row_Pos == 3) - { - Canal_Actual = Inicial + 13; - goto Salida_DMX; - } - // posicion 15 - if (LCD_Col_Pos == 16 && LCD_Row_Pos == 3) - { - Canal_Actual = Inicial + 14; - goto Salida_DMX; - } - Salida_DMX: - Num_Row_Pos = LCD_Row_Pos; - Num_Col_Pos = LCD_Col_Pos + 1; - Num_Val = DMX_Values[Canal_Actual]; // para dejar el numero que estaba si no se cambia - Numerico_Calc(1); - if (Num_Val == 612) // ubicar - { - Ubicar(); - Num_Col_Pos = Num_Col_Pos - 4; - } - if (Num_Val == 712) // analogo - { - Analog_Read_DMX(Num_Col_Pos - 2, Num_Row_Pos); - Num_Col_Pos = Num_Col_Pos - 4; - goto Banco; - } - if (Num_Val > 255) - { - Num_Val = 255; - Numerico_Write (255, Num_Col_Pos + 2, Num_Row_Pos); - } - ArduinoDmx0.TxBuffer[Canal_Actual - 1] = Num_Val; - DMX_Values[Canal_Actual] = Num_Val; - goto Banco; -} - -void Cursor_Conf_Clear() -{ - for (byte Conteo_Col = 0; Conteo_Col <= 19; Conteo_Col ++) - { - for (byte Conteo_Row = 0; Conteo_Row <= 3; Conteo_Row ++) - { - Cursor_Conf[Conteo_Row][Conteo_Col] = 0; - } - } -} - -void GUI_Navegar(byte matrix, int banco) -{ - int Boton_Delay_Cursor = 300; // delay de lectura de boton - byte LCD_Col_Pos_Ant; // saber el estado anterior para borrar cursor - byte LCD_Row_Pos_Ant; // saber el estado anterior para borrar cursor - // guardar valor anterior de row col - LCD_Col_Pos_Ant = LCD_Col_Pos; - LCD_Row_Pos_Ant = LCD_Row_Pos; - // Dibujar cursor - lcd.setCursor (LCD_Col_Pos, LCD_Row_Pos); - lcd.print(">"); - // navegacion - Dibujar: - byte Dibujar_Cursor = 0; // saber si dibujar cursor para evitar repeticiones en lcd, 0 no dibujar, 1 dibujar >, 2 dibujar + - // LCD Back Light * - digitalWrite(Boton_Array_1, LOW); // lectura linea 1 - if (digitalRead(Boton_Array_D) == LOW) - { - delay(Boton_Delay_Teclado); - Light_En(); - } - digitalWrite(Boton_Array_1, HIGH); // lectura linea 1 - // Left - if (digitalRead(Boton_Left) == LOW) - { - delay (Boton_Delay_Cursor); - byte Salida_Left = 0; - byte LCD_Col_Pos_Temp = 0; - LCD_Col_Pos_Temp = LCD_Col_Pos; - while (Salida_Left == 0) - { - if (LCD_Col_Pos_Temp == 0) - { - LCD_Col_Pos_Temp = 20; - } - LCD_Col_Pos_Temp = LCD_Col_Pos_Temp - 1; - if (Cursor_Conf[LCD_Row_Pos][LCD_Col_Pos_Temp] == 1) - { - LCD_Col_Pos = LCD_Col_Pos_Temp; - Dibujar_Cursor = 1; - Salida_Left = 1; - } - } - goto Salida; - } - // Right - if (digitalRead(Boton_Right) == LOW) - { - delay(Boton_Delay_Cursor); - byte Salida_Right = 0; - byte LCD_Col_Pos_Temp = 0; - LCD_Col_Pos_Temp = LCD_Col_Pos; - while (Salida_Right == 0) - { - LCD_Col_Pos_Temp = LCD_Col_Pos_Temp + 1; - if (LCD_Col_Pos_Temp >= 20) - { - LCD_Col_Pos_Temp = 0; // regresar al cero - } - if (Cursor_Conf[LCD_Row_Pos][LCD_Col_Pos_Temp] == 1) - { - LCD_Col_Pos = LCD_Col_Pos_Temp; - Dibujar_Cursor = 1; - Salida_Right = 1; - } - } - goto Salida; - } - // Down - if (digitalRead(Boton_Down) == LOW) - { - delay(Boton_Delay_Cursor); - byte Salida_Down = 0; - byte LCD_Row_Pos_Temp = 0; - LCD_Row_Pos_Temp = LCD_Row_Pos; - while (Salida_Down == 0) - { - LCD_Row_Pos_Temp = LCD_Row_Pos_Temp + 1; - if (LCD_Row_Pos_Temp >= 4) - { - LCD_Row_Pos_Temp = 0; // regresar al cero - } - if (Cursor_Conf[LCD_Row_Pos_Temp][LCD_Col_Pos] == 1) - { - LCD_Row_Pos = LCD_Row_Pos_Temp; - Dibujar_Cursor = 1; - Salida_Down = 1; - } - } - goto Salida; - } - // Up - if (digitalRead(Boton_Up) == LOW) - { - delay(Boton_Delay_Cursor); - byte Salida_Up = 0; - byte LCD_Row_Pos_Temp; - LCD_Row_Pos_Temp = LCD_Row_Pos; - while (Salida_Up == 0) - { - if (LCD_Row_Pos_Temp <= 0) - { - LCD_Row_Pos_Temp = 4; - } - LCD_Row_Pos_Temp = LCD_Row_Pos_Temp - 1; - if (Cursor_Conf[LCD_Row_Pos_Temp][LCD_Col_Pos] == 1) - { - Dibujar_Cursor = 1; - LCD_Row_Pos = LCD_Row_Pos_Temp; - Salida_Up = 1; - } - } - goto Salida; - } - // Center - if (digitalRead(Boton_Center) == LOW) - { - delay(Boton_Delay_Cursor); - byte Salida_Center = 0; - while (Salida_Center == 0) - { - if (Cursor_Conf[LCD_Row_Pos][LCD_Col_Pos] == 1) - { - Dibujar_Cursor = 2; // dibujar + - Salida_Center = 1; - } - } - } -Salida: - // Dibujar Cursor - if (Dibujar_Cursor > 0) - { - if (Dibujar_Cursor == 1) - { - // borra el anterior - lcd.setCursor (LCD_Col_Pos_Ant, LCD_Row_Pos_Ant); - lcd.print(" "); - // escribir > - lcd.setCursor (LCD_Col_Pos, LCD_Row_Pos); - lcd.print(">"); - // matrix print posicion - if (matrix == 1) - { - // banco inicial - if (LCD_Col_Pos == 12 && LCD_Row_Pos == 0) - { - lcd.setCursor(1, 0); - lcd.print("---"); - goto salida; - } - // banco final - if (LCD_Col_Pos == 16 && LCD_Row_Pos == 0) - { - lcd.setCursor(1, 0); - lcd.print("---"); - goto salir; - } - // Memory - if (LCD_Col_Pos == 4 && LCD_Row_Pos == 0) - { - lcd.setCursor(1, 0); - lcd.print("---"); - goto salida; - } - // Unitary - if (LCD_Col_Pos == 8 && LCD_Row_Pos == 0) - { - lcd.setCursor(1, 0); - lcd.print("---"); - goto salida; - } - // banco 1 - if (LCD_Col_Pos == 0 && LCD_Row_Pos == 1) - { - Numerico_Write (banco, 1, 0); - goto salida; - } - // banco 2 - if (LCD_Col_Pos == 4 && LCD_Row_Pos == 1) - { - Numerico_Write (banco + 1, 1, 0); - goto salida; - } - // banco 3 - if (LCD_Col_Pos == 8 && LCD_Row_Pos == 1) - { - Numerico_Write (banco + 2, 1, 0); - goto salida; - } - // banco 4 - if (LCD_Col_Pos == 12 && LCD_Row_Pos == 1) - { - Numerico_Write (banco + 3, 1, 0); - goto salida; - } - // banco 5 - if (LCD_Col_Pos == 16 && LCD_Row_Pos == 1) - { - Numerico_Write (banco + 4, 1, 0); - goto salida; - } - // banco 6 - if (LCD_Col_Pos == 0 && LCD_Row_Pos == 2) - { - Numerico_Write (banco + 5, 1, 0); - goto salida; - } - // banco 7 - if (LCD_Col_Pos == 4 && LCD_Row_Pos == 2) - { - Numerico_Write (banco + 6, 1, 0); - goto salida; - } - // banco 8 - if (LCD_Col_Pos == 8 && LCD_Row_Pos == 2) - { - Numerico_Write (banco + 7, 1, 0); - goto salida; - } - // banco 9 - if (LCD_Col_Pos == 12 && LCD_Row_Pos == 2) - { - Numerico_Write (banco + 8, 1, 0); - goto salida; - } - // banco 10 - if (LCD_Col_Pos == 16 && LCD_Row_Pos == 2) - { - Numerico_Write (banco + 9, 1, 0); - goto salida; - } - // banco 11 - if (LCD_Col_Pos == 0 && LCD_Row_Pos == 3) - { - Numerico_Write (banco + 10, 1, 0); - goto salida; - } - // banco 12 - if (LCD_Col_Pos == 4 && LCD_Row_Pos == 3) - { - Numerico_Write (banco + 11, 1, 0); - goto salida; - } - // banco 13 - if (LCD_Col_Pos == 8 && LCD_Row_Pos == 3) - { - Numerico_Write (banco + 12, 1, 0); - goto salida; - } - // banco 14 - if (LCD_Col_Pos == 12 && LCD_Row_Pos == 3) - { - Numerico_Write (banco + 13, 1, 0); - goto salida; - } - // banco 15 - if (LCD_Col_Pos == 16 && LCD_Row_Pos == 3) - { - Numerico_Write (banco + 14, 1, 0); - goto salida; - } - // escribir guion de bancos - salida: - lcd.setCursor(16, 0); - lcd.print("-"); - salir: - { - } - } - } - else - { - // escribir + - lcd.setCursor (LCD_Col_Pos, LCD_Row_Pos); - lcd.print("+"); - } - //salida - LCD_Col_Pos_Ant = LCD_Col_Pos; - LCD_Row_Pos_Ant = LCD_Row_Pos; - if (Dibujar_Cursor == 2) - { - goto Salir; - } - else - { - Dibujar_Cursor = 0; - } - } - goto Dibujar; - Salir: {} -} - -void GUI_Memory_Init() -{ - inicio: - int salir = 0; - lcd.clear (); - // Texto - lcd.setCursor (0, 0); - lcd.print("Initial Memory:"); - lcd.setCursor (2, 2); - lcd.print("Empty"); - lcd.setCursor (9, 2); - lcd.print("Load"); - lcd.setCursor (15, 2); - lcd.print("Clear"); - // bank - lcd.setCursor(18, 0); - lcd.print("b"); - if (Universo_Actual == 0) - { - lcd.print("-"); - } - else - { - lcd.print(Universo_Actual); - } - // Cursor - LCD_Col_Pos = 1; // posicion de cursor - LCD_Row_Pos = 2; - // configuracion de cursor - Cursor_Conf_Clear(); // limpiar array - // Acciones - Cursor_Conf[2][1] = 1; // Empty - Cursor_Conf[2][8] = 1; // Load - Cursor_Conf[2][14] = 1; // Clear - // navegar - GUI_Navegar(0, 0); - // Acciones - // Load - if (LCD_Col_Pos == 8 && LCD_Row_Pos == 2) - { - salir = EEPROM_Load(); - if (salir == 1) - { - goto inicio; - } - GUI_Control_Options(); - } - // Clear - if (LCD_Col_Pos == 14 && LCD_Row_Pos == 2) - { - salir = EEPROM_Clear(); - if (salir == 1) - { - goto inicio; - } - GUI_Control_Options(); - } - // Empty - if (LCD_Col_Pos == 1 && LCD_Row_Pos == 2) - { - GUI_Control_Options(); - } -} - -int GUI_Memory_Bank(byte Opcion) -{ - // regresa 1 si se selecciona salir, de lo contrario 0 - // recibe opcion para pintar en la pantalla lo que se selecciono - int salir = 0; - lcd.clear (); - delay (200); // retardo para no seleccionar inmediatamente la opcion del banco - // Texto - lcd.setCursor (6, 0); - lcd.print("Memory Bank:"); - lcd.setCursor (1, 1); - lcd.print("Bank1 Bank4 Bank7"); - lcd.setCursor (1, 2); - lcd.print("Bank2 Bank5 Bank8"); - lcd.setCursor (1, 3); - lcd.print("Bank3 Bank6 Exit"); - switch (Opcion) - { - case 1: - lcd.setCursor (1, 0); - lcd.print("Save"); - break; - case 2: - lcd.setCursor (1, 0); - lcd.print("Load"); - break; - case 3: - lcd.setCursor (0, 0); - lcd.print("Clear"); - break; - } - // Universo Actual - lcd.setCursor (19, 0); - if (Universo_Actual == 0) - { - lcd.print("-"); - } - else - { - lcd.print(Universo_Actual); - } - // Cursor inicial - LCD_Col_Pos = 0; // posicion de cursor - LCD_Row_Pos = 1; - // configuracion de cursor - Cursor_Conf_Clear(); // limpiar array - // Acciones - Cursor_Conf[1][0] = 1; // Bank 1 - Cursor_Conf[2][0] = 1; // Bank 2 - Cursor_Conf[3][0] = 1; // Bank 3 - Cursor_Conf[1][7] = 1; // Bank 4 - Cursor_Conf[2][7] = 1; // Bank 5 - Cursor_Conf[3][7] = 1; // Bank 6 - Cursor_Conf[1][14] = 1; // Bank 7 - Cursor_Conf[2][14] = 1; // Bank 8 - Cursor_Conf[3][14] = 1; // Exit - // navegar - GUI_Navegar(0, 0); - // Acciones - // Bank 1 - if (LCD_Col_Pos == 0 && LCD_Row_Pos == 1) - { - Universo_Actual = 1; - goto Salida; - } - // Bank 2 - if (LCD_Col_Pos == 0 && LCD_Row_Pos == 2) - { - Universo_Actual = 2; - goto Salida; - } - // Bank 3 - if (LCD_Col_Pos == 0 && LCD_Row_Pos == 3) - { - Universo_Actual = 3; - goto Salida; - } - // Bank 4 - if (LCD_Col_Pos == 7 && LCD_Row_Pos == 1) - { - Universo_Actual = 4; - goto Salida; - } - // Bank 5 - if (LCD_Col_Pos == 7 && LCD_Row_Pos == 2) - { - Universo_Actual = 5; - goto Salida; - } - // Bank 6 - if (LCD_Col_Pos == 7 && LCD_Row_Pos == 3) - { - Universo_Actual = 6; - goto Salida; - } - // Bank 7 - if (LCD_Col_Pos == 14 && LCD_Row_Pos == 1) - { - Universo_Actual = 7; - goto Salida; - } - // Bank 8 - if (LCD_Col_Pos == 14 && LCD_Row_Pos == 2) - { - Universo_Actual = 8; - goto Salida; - } - // Exit - if (LCD_Col_Pos == 14 && LCD_Row_Pos == 3) - { - salir = 1; - } - Salida: - return salir; -} - -void GUI_Memory() -{ - iniciar: - lcd.clear (); - // Texto - lcd.setCursor (0, 0); - lcd.print("Memory: b"); - if (Universo_Actual == 0) - { - lcd.print("-"); - } - else - { - lcd.print(Universo_Actual); - } - lcd.setCursor (1, 1); - lcd.print("Save"); - lcd.setCursor (1, 2); - lcd.print("Load"); - lcd.setCursor (1, 3); - lcd.print("Clear"); - lcd.setCursor (7, 2); - lcd.print("ClearAll"); - lcd.setCursor (7, 1); - lcd.print("BlackOut"); - lcd.setCursor (16, 3); - lcd.print("Exit"); - lcd.setCursor (7, 3); - lcd.print("EmptyRAM"); - // Cursor - LCD_Col_Pos = 0; // posicion de cursor - LCD_Row_Pos = 1; - // configuracion de cursor - Cursor_Conf_Clear(); // limpiar array - // Acciones - Cursor_Conf[1][0] = 1; // Save - Cursor_Conf[2][0] = 1; // Load - Cursor_Conf[3][0] = 1; // Clear - Cursor_Conf[2][6] = 1; // Clear All - Cursor_Conf[3][6] = 1; // Empty RAM - Cursor_Conf[1][6] = 1; // Black Out - Cursor_Conf[3][15] = 1; // Exit - // navegar - regresa: - GUI_Navegar(0, 0); - // Acciones - // Load - if (LCD_Col_Pos == 0 && LCD_Row_Pos == 2) - { - if (EEPROM_Load() == 1) - { - goto iniciar; - } - goto salida; - } - // Clear - if (LCD_Col_Pos == 0 && LCD_Row_Pos == 3) - { - if (EEPROM_Clear() == 1) - { - goto iniciar; - } - goto salida; - } - // Clear All - if (LCD_Col_Pos == 6 && LCD_Row_Pos == 2) - { - EEPROM_Clear_All(); - goto salida; - } - // Save - if (LCD_Col_Pos == 0 && LCD_Row_Pos == 1) - { - if (EEPROM_Save() == 1) - { - goto iniciar; - } - goto salida; - } - // Empty RAM - if (LCD_Col_Pos == 6 && LCD_Row_Pos == 3) - { - EEPROM_Empty(); - goto salida; - } - // Black Out - if (LCD_Col_Pos == 6 && LCD_Row_Pos == 1) - { - Black_Out(); - goto regresa; - } - // Exit - if (LCD_Col_Pos == 15 && LCD_Row_Pos == 3) - { - - } - salida: {} -} - -void GUI_Control_Secuencer() -{ - // secuenciador de bancos guardados en eeprom - int Delay_Secuencia = 1; - int First_Bank = 1; - int Final_Bank = 8; - lcd.clear (); - - // Texto - lcd.setCursor (0, 0); - lcd.print("Secuencer Banks: b"); - if (Universo_Actual == 0) - { - lcd.print("-"); - } - else - { - lcd.print(Universo_Actual); - } - lcd.setCursor (4, 1); - lcd.print("Delay 001x100=mS"); - lcd.setCursor (0, 2); - lcd.print("FirstBank 001 Exit"); - lcd.setCursor (0, 3); - lcd.print("FinalBank 008 Start"); - // Cursor - LCD_Col_Pos = 9; // posicion de cursor - LCD_Row_Pos = 1; - // configuracion de cursor - Cursor_Conf_Clear(); // limpiar array - // Acciones - Cursor_Conf[1][9] = 1; // Delay - Cursor_Conf[2][9] = 1; // First Bank - Cursor_Conf[3][9] = 1; // Final Bank - Cursor_Conf[2][14] = 1; // Control - Cursor_Conf[3][14] = 1; // start - inicio: - lcd.setCursor (15, 3); - lcd.print("Start"); - lcd.noBlink(); - - // navegar - GUI_Navegar(0, 0); - - // Acciones - // Delay - if (LCD_Col_Pos == 9 && LCD_Row_Pos == 1) - { - Num_Row_Pos = 1; - Num_Col_Pos = 10; - Num_Val = Delay_Secuencia; // para dejar el numero que estaba si no se cambia - Numerico_Calc(0); - if (Num_Val == 0) - { - Numerico_Write (1, 10, 1); - Delay_Secuencia = 1; - Numerico_Write (Delay_Secuencia, 10, 1); - } - else - { - Delay_Secuencia = Num_Val; // por el multiplicador - } - if (Num_Val > 100) - { - Delay_Secuencia = 100; - Numerico_Write (Delay_Secuencia, 10, 1); - } - goto inicio; - } - // First Bank - if (LCD_Col_Pos == 9 && LCD_Row_Pos == 2) - { - Num_Row_Pos = 2; - Num_Col_Pos = 10; - Num_Val = First_Bank; // para dejar el numero que estaba si no se cambia - Numerico_Calc(0); - First_Bank = Num_Val; - if (Num_Val == 0) - { - First_Bank = 1; - Numerico_Write (First_Bank, 10, 2); - } - if (Num_Val > 8) - { - Numerico_Write (8, 10, 2); - First_Bank = 8; - } - goto inicio; - } - // Final Bank - if (LCD_Col_Pos == 9 && LCD_Row_Pos == 3) - { - Num_Row_Pos = 3; - Num_Col_Pos = 10; - Num_Val = Final_Bank; // para dejar el numero que estaba si no se cambia - Numerico_Calc(0); - Final_Bank = Num_Val; - if (Num_Val == 0) - { - Final_Bank = 1; - Numerico_Write (Final_Bank, 10, 3); - } - if (Num_Val > 8) - { - Numerico_Write (8, 10, 2); - Final_Bank = 8; - } - goto inicio; - } - // Control - if (LCD_Col_Pos == 14 && LCD_Row_Pos == 2) - { - // restablecer salida dmx como estaba antes de entrar - for(int Canal = 0; Canal <= 512; Canal ++) - { - ArduinoDmx0.TxBuffer[Canal] = DMX_Values[Canal]; // salida a DMX - } - GUI_Control_Options (); - } - // start - if (LCD_Col_Pos == 14 && LCD_Row_Pos == 3) - { - // validar - if (First_Bank == Final_Bank) - { - First_Bank = 1; - Numerico_Write (First_Bank, 10, 2); - Final_Bank = 8; - Numerico_Write (Final_Bank, 10, 2); - goto inicio; - } - // LCD - lcd.setCursor (14, 3); - lcd.print("+"); - lcd.setCursor (15, 3); - lcd.print("Stop "); - // establecer reversa o adelante - byte Adelante_Reversa = 0; // 0 Adelante, 1 Reversa - // adelante - if (First_Bank < Final_Bank) - { - Adelante_Reversa = 0; - } - // reversa - if (First_Bank > Final_Bank) - { - Adelante_Reversa = 1; - } - // establecer bancos a secuenciar - byte Bancos [9] = {0, 0, 0, 0, 0, 0, 0, 0}; - if (Adelante_Reversa == 0) - { - for (byte Bank = 1; Bank <= 8; Bank ++) - { - if (Bank >= First_Bank && Bank <= Final_Bank) - { - Bancos[Bank] = 1; - } - } - } - if (Adelante_Reversa == 1) - { - for (byte Bank = 8; Bank >= 1; Bank --) - { - if (Bank <= First_Bank && Bank >= Final_Bank) - { - Bancos[Bank] = 1; - } - } - } - //Secuenciar - byte value = 0; - lcd.blink(); - - // adelante - if (Adelante_Reversa == 0) - { - contar: - for (byte conteo = 1; conteo <= 8; conteo ++) - { - if (Bancos [conteo] == 1) - { - lcd.setCursor (19, 0); - lcd.print(conteo); - lcd.setCursor (19, 3); - for (int canal = 0; canal <= 511; canal ++) - { - switch (conteo) - { - case 1: - value = EEPROM.read(canal); - ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX - break; - case 2: - value = EEPROM.read(canal + 512); - ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX - break; - case 3: - value = EEPROM.read(canal + 1024); - ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX - break; - case 4: - value = EEPROM.read(canal + 1536); - ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX - break; - case 5: - value = EEPROM.read(canal + 2048); - ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX - break; - case 6: - value = EEPROM.read(canal + 2560); - ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX - break; - case 7: - value = EEPROM.read(canal + 3072); - ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX - break; - case 8: - value = EEPROM.read(canal + 3584); - ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX - break; - } - } - //delay - long delay_contar = Delay_Secuencia * 100; - while (digitalRead(Boton_Center) == HIGH) // lectura del boton centro - { - for (long contar = 0; contar <= delay_contar; contar ++) - { - delay(1); - if (digitalRead(Boton_Center) == LOW) - { - goto salida; - } - } - goto Delay_Salir; - } - salida: - delay(500); // rebote de boton - goto inicio; - Delay_Salir: {} - } - } - goto contar; - } - - // reversa - if (Adelante_Reversa == 1) - { - contar_rev: - for (byte conteo = 8; conteo >= 1; conteo --) - { - if (Bancos [conteo] == 1) - { - lcd.setCursor (19, 0); - lcd.print(conteo); - lcd.setCursor (19, 3); - for (int canal = 0; canal <= 511; canal ++) - { - switch (conteo) - { - case 1: - value = EEPROM.read(canal); - ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX - break; - case 2: - value = EEPROM.read(canal + 512); - ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX - break; - case 3: - value = EEPROM.read(canal + 1024); - ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX - break; - case 4: - value = EEPROM.read(canal + 1536); - ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX - break; - case 5: - value = EEPROM.read(canal + 2048); - ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX - break; - case 6: - value = EEPROM.read(canal + 2560); - ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX - break; - case 7: - value = EEPROM.read(canal + 3072); - ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX - break; - case 8: - value = EEPROM.read(canal + 3584); - ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX - break; - } - } - //delay - long delay_contar = Delay_Secuencia * 100; - while (digitalRead(Boton_Center) == HIGH) // lectura del boton centro - { - for (long contar = 0; contar <= delay_contar; contar ++) - { - delay(1); - if (digitalRead(Boton_Center) == LOW) - { - goto salida_rev; - } - } - goto Delay_Salir_Rev; - } - salida_rev: - delay(500); // rebote de boton - goto inicio; - Delay_Salir_Rev: {} - } - } - goto contar_rev; - } - } - goto inicio; -} - -void Black_Out() -{ - lcd.setCursor (15, 1); - lcd.blink(); - // limpiar universo - for(int Canal = 1; Canal <= 512; Canal ++) - { - ArduinoDmx0.TxBuffer[Canal - 1] = 0; - } - // esperar al boton centro para cancelar - while (digitalRead(Boton_Center) == HIGH) - { - } - delay(300); // retardo de rebote de boton - // regresar el universo a su lugar - for(int Canal = 1; Canal <= 512; Canal ++) - { - ArduinoDmx0.TxBuffer[Canal - 1] = DMX_Values[Canal]; - } - lcd.setCursor (6, 2); - lcd.noBlink(); -} - -int EEPROM_Save() -{ - // guarda el universo en la eeprom - // regresa 1 si se selecciona exit - int cancel = 0; // regresa 1 si se selecciona salir - int bank; // regresa 1 si se selecciona salir - int EEPROM_Add = 0; // direccion de eeprom para universos - bank = GUI_Memory_Bank(1); // seleccinar banco - if (bank == 1) - { - cancel = 1; - goto salida; - } - lcd.clear (); - lcd.setCursor (1, 1); - lcd.print ("Memory Saving..."); - lcd.setCursor (1, 2); - lcd.print ("Bank: "); - lcd.setCursor (7, 2); - lcd.print (Universo_Actual); - lcd.setCursor (19, 3); - lcd.blink(); - for(int Canal = 0; Canal <= 511; Canal ++) - { - // Escritura de universo EEPROM - switch (Universo_Actual) - { - case 1: - EEPROM_Add = 0 + Canal; - break; - case 2: - EEPROM_Add = 512 + Canal; - break; - case 3: - EEPROM_Add = 1024 + Canal; - break; - case 4: - EEPROM_Add = 1536 + Canal; - break; - case 5: - EEPROM_Add = 2048 + Canal; - break; - case 6: - EEPROM_Add = 2560 + Canal; - break; - case 7: - EEPROM_Add = 3072 + Canal; - break; - case 8: - EEPROM_Add = 3584 + Canal; - if (EEPROM_Add > EEPROM_Limit) - { - EEPROM_Add = EEPROM_Limit; - } - break; - } - EEPROM.write(EEPROM_Add, DMX_Values[Canal + 1]); // lectura desde EEPROM - } - lcd.clear (); - lcd.setCursor (3, 1); - lcd.print ("Memory Saved!"); - lcd.setCursor (3, 2); - lcd.print ("Bank: "); - lcd.print (Universo_Actual); - lcd.setCursor (19, 3); - delay (1000); - lcd.noBlink(); - salida: - return cancel; -} - -int EEPROM_Load() -{ - // guarda los valores en la eeprom - // regresa 1 si se selecciona exit - int cancel = 0; // regresa 1 si se selecciona salir - int bank; // regresa 1 si se selecciona salir - int EEPROM_Add = 0; // seleccion de universo - bank = GUI_Memory_Bank(2); // seleccinar banco - if (bank == 1) - { - cancel = 1; - goto salida; - } - lcd.clear (); - for(int Canal = 1; Canal <= 512; Canal ++) - { - // Escritura de universo EEPROM - switch (Universo_Actual) - { - case 1: - EEPROM_Add = 0 + Canal - 1; - break; - case 2: - EEPROM_Add = 512 + Canal - 1; - break; - case 3: - EEPROM_Add = 1024 + Canal - 1; - break; - case 4: - EEPROM_Add = 1536 + Canal - 1; - break; - case 5: - EEPROM_Add = 2048 + Canal - 1; - break; - case 6: - EEPROM_Add = 2560 + Canal - 1; - break; - case 7: - EEPROM_Add = 3072 + Canal - 1; - break; - case 8: - EEPROM_Add = 3584 + Canal - 1; - if (EEPROM_Add > EEPROM_Limit) - { - EEPROM_Add = EEPROM_Limit; - } - break; - } - DMX_Values[Canal] = EEPROM.read(EEPROM_Add); // lectura desde EEPROM - ArduinoDmx0.TxBuffer[Canal - 1] = DMX_Values[Canal]; // salida a DMX - } - lcd.clear (); - lcd.setCursor (3, 1); - lcd.print ("Memory Loaded!"); - lcd.setCursor (3, 2); - lcd.print ("Bank: "); - lcd.print (Universo_Actual); - lcd.setCursor (19, 3); - lcd.blink(); - delay (1000); - lcd.noBlink(); - salida: - return cancel; -} - -void EEPROM_Load_Init() -{ - // carga los valores en la eeprom al inicio - int EEPROM_Add = 0; - Universo_Actual = EEPROM.read(Bank_Init_Add); - if (Universo_Actual == 0) - { - goto salir; - } - for(int Canal = 1; Canal <= 512; Canal ++) - { - // Escritura de universo EEPROM - switch (Universo_Actual) - { - case 1: - EEPROM_Add = 0 + Canal - 1; - break; - case 2: - EEPROM_Add = 512 + Canal - 1; - break; - case 3: - EEPROM_Add = 1024 + Canal - 1; - break; - case 4: - EEPROM_Add = 1536 + Canal - 1; - break; - case 5: - EEPROM_Add = 2048 + Canal - 1; - break; - case 6: - EEPROM_Add = 2560 + Canal - 1; - break; - case 7: - EEPROM_Add = 3072 + Canal - 1; - break; - case 8: - EEPROM_Add = 3584 + Canal - 1; - if (EEPROM_Add > EEPROM_Limit) - { - EEPROM_Add = EEPROM_Limit; - } - break; - } - DMX_Values[Canal] = EEPROM.read(EEPROM_Add); // lectura desde EEPROM - ArduinoDmx0.TxBuffer[Canal - 1] = DMX_Values[Canal]; // salida a DMX - } - lcd.clear (); - lcd.setCursor (3, 1); - lcd.print ("Memory Loaded!"); - lcd.setCursor (3, 2); - lcd.print ("Bank: "); - lcd.print (Universo_Actual); - lcd.setCursor (10, 2); - lcd.blink(); - delay (2000); - lcd.noBlink(); - salir: - {} -} - -void EEPROM_Empty() -{ - // solo borra la ram - // no hay retorno al menu anterior - lcd.clear (); - for(int Canal = 1; Canal <= 512; Canal ++) - { - DMX_Values[Canal] = 0; // lectura desde EEPROM - ArduinoDmx0.TxBuffer[Canal - 1] = 0; // salida a DMX - } - lcd.clear (); - lcd.setCursor (3, 1); - lcd.print ("Memory Emptied!"); - lcd.setCursor (3, 2); - lcd.print ("Bank: RAM"); - lcd.setCursor (19, 3); - lcd.blink(); - delay (1000); - lcd.noBlink(); -} - -int EEPROM_Clear() -{ - // Pone en ceros la memoria EEPROM - // regresa 1 si se selecciona exit - int cancel = 0; // regresa 1 si se selecciona salir - int bank; // regresa 1 si se selecciona salir - int EEPROM_Add = 0; // direccion de eeprom para universos - bank = GUI_Memory_Bank(3); // seleccinar banco - if (bank == 1) // si se selecciono salir - { - cancel = 1; - goto salida; - } - lcd.clear (); - lcd.setCursor (1, 1); - lcd.print ("Memory Cleaning..."); - lcd.setCursor (1, 2); - lcd.print ("Bank: "); - lcd.setCursor (7, 2); - lcd.print (Universo_Actual); - lcd.setCursor (19, 3); - lcd.blink(); - for(int Canal = 0; Canal <= 511; Canal ++) - { - DMX_Values[Canal] = 0; // lectura desde EEPROM - ArduinoDmx0.TxBuffer[Canal] = 0; // salida a DMX - // Escritura de universo EEPROM - switch (Universo_Actual) - { - case 1: - EEPROM_Add = 0 + Canal; - break; - case 2: - EEPROM_Add = 512 + Canal; - break; - case 3: - EEPROM_Add = 1024 + Canal; - break; - case 4: - EEPROM_Add = 1536 + Canal; - break; - case 5: - EEPROM_Add = 2048 + Canal; - break; - case 6: - EEPROM_Add = 2560 + Canal; - break; - case 7: - EEPROM_Add = 3072 + Canal; - break; - case 8: - EEPROM_Add = 3584 + Canal; - if (EEPROM_Add > EEPROM_Limit) - { - EEPROM_Add = EEPROM_Limit; - } - break; - } - EEPROM.write (EEPROM_Add, 0); // escritura EEPROM - } - lcd.clear (); - lcd.setCursor (2, 1); - lcd.print ("Memory Cleaned!"); - lcd.setCursor (2, 2); - lcd.print ("Bank: "); - lcd.print (Universo_Actual); - lcd.setCursor (19, 3); - delay (1000); - lcd.noBlink(); - salida: - return cancel; -} - -void EEPROM_Clear_All() -{ - // Pone en ceros la memoria EEPROM toda - lcd.clear (); - lcd.setCursor (1, 1); - lcd.print ("All"); - lcd.setCursor (1, 2); - lcd.print ("Memory Cleaning..."); - lcd.setCursor (19, 2); - lcd.blink(); - for(int Canal = 0; Canal <= EEPROM_Limit; Canal ++) - { - EEPROM.write (Canal, 0); // escritura EEPROM - if (Canal <= 511) - { - DMX_Values[Canal + 1] = 0; - ArduinoDmx0.TxBuffer[Canal] = 0; // salida a DMX - } - } - lcd.clear (); - lcd.noBlink(); - lcd.setCursor (2, 2); - lcd.print ("Memory Cleaned!"); - lcd.setCursor (2, 1); - lcd.print ("All"); - Universo_Actual = 0; - delay (1000); -} - -void GUI_Control_Options() -{ - inicio: - // LCD - lcd.clear (); - lcd.setCursor (18, 0); - lcd.print ("b"); - if (Universo_Actual == 0) - { - lcd.print ("-"); - } - else - { - lcd.print (Universo_Actual); - } - lcd.setCursor (2, 0); - lcd.print ("Convert"); - lcd.setCursor (2, 1); - lcd.print ("Unitary"); - lcd.setCursor (2, 2); - lcd.print ("Matrix"); - lcd.setCursor (2, 3); - lcd.print ("Chaser"); - lcd.setCursor (11, 3); - lcd.print ("Multiply"); - lcd.setCursor (11, 0); - lcd.print ("Config"); - lcd.setCursor (11, 2); - lcd.print ("Secuencer"); - lcd.setCursor (11, 1); - lcd.print ("Memory"); - // Cursor - LCD_Col_Pos = 1; // posicion de cursor - LCD_Row_Pos = 2; - // configuracion de cursor - Cursor_Conf_Clear(); // limpiar array - // Acciones - Cursor_Conf[1][1] = 1; // Unitary - Cursor_Conf[2][1] = 1; // Matrix - Cursor_Conf[3][1] = 1; // Chaser - Cursor_Conf[3][10] = 1; // Multiply - Cursor_Conf[0][10] = 1; // Config - Cursor_Conf[2][10] = 1; // Secuencer - Cursor_Conf[1][10] = 1; // Memory - Cursor_Conf[0][1] = 1; // Convert - // navegar - GUI_Navegar(0, 0); - // Acciones - // Unitary - if (LCD_Col_Pos == 1 && LCD_Row_Pos == 1) - { - GUI_Control_Unit(); - } - // Matrix - if (LCD_Col_Pos == 1 && LCD_Row_Pos == 2) - { - GUI_Control_Matrix(); - } - // Chaser - if (LCD_Col_Pos == 1 && LCD_Row_Pos == 3) - { - GUI_Control_Chaser(); - } - // Multiply - if (LCD_Col_Pos == 10 && LCD_Row_Pos == 3) - { - GUI_Control_Multiply(); - } - // Config - if (LCD_Col_Pos == 10 && LCD_Row_Pos == 0) - { - GUI_Config(); - } - // Secuencer - if (LCD_Col_Pos == 10 && LCD_Row_Pos == 2) - { - GUI_Control_Secuencer(); - } - // Converter - if (LCD_Col_Pos == 1 && LCD_Row_Pos == 0) - { - GUI_Convert(); - } - // Memory - if (LCD_Col_Pos == 10 && LCD_Row_Pos == 1) - { - GUI_Memory(); - goto inicio; - } -} - -void GUI_Convert() -{ - int valor = 0; // aqui el valor a calcular - int valor_temp = 0; // aqui el valor temporal para las cuentas - int valor_resto = 0; // aqui el valor del resto de la divicion - int valor_Bin [10] = {0,0,0,0,0,0,0,0,0,0}; // aqui el valor descompuesto en binario - lcd.clear (); - lcd.setCursor (0, 0); - lcd.print ("Bin: OOOOOOOOO I=On"); - lcd.setCursor (5, 1); - lcd.print ("124813612 O=Off"); - lcd.setCursor (9, 2); - lcd.print ("62425"); - lcd.setCursor (0, 3); - lcd.print ("Dec: 000 86 Exit"); - // Cursor - LCD_Col_Pos = 4; // posicion de cursor - LCD_Row_Pos = 3; // posicion e cursor - // configuracion de cursor - Cursor_Conf_Clear(); // limpiar array - // Cursores - Cursor_Conf[0][4] = 1; // Bin - Cursor_Conf[3][4] = 1; // Dec - Cursor_Conf[3][15] = 1; // Exit - //Navegacion: - calc: - GUI_Navegar(0, 0); - // Acciones - // Exit - if (LCD_Col_Pos == 15 && LCD_Row_Pos == 3) - { - GUI_Control_Options(); - } - // Binario a decimal - if (LCD_Col_Pos == 4 && LCD_Row_Pos == 0) - { - // boton de centro para salir - // boton de lados para navegar - // boton arriba abajo para cambiar valor - byte cursor = 5; // posicion de cursor - int boton_retardo = 250; // retardo de boton para estabilidad - byte calcular = 0; // calcular binario a decimal - byte calcular_val = 0; // valor a meter a la matriz para calcular - lcd.blink(); - lcd.setCursor (5, 0); - while (digitalRead(Boton_Center) == HIGH) // salida - { - if (digitalRead(Boton_Right) == LOW) - { - delay(boton_retardo); // esperar a estabilidad - cursor = cursor + 1; - if (cursor > 13) - { - cursor = 5; // regresar al principio - } - lcd.setCursor (cursor, 0); - } - if (digitalRead(Boton_Left) == LOW) - { - delay(boton_retardo); // esperar a estabilidad - cursor = cursor - 1; - if (cursor < 5) - { - cursor = 13; // regresar al final - } - lcd.setCursor (cursor, 0); - } - if (digitalRead(Boton_Up) == LOW) - { - delay(boton_retardo); // esperar a estabilidad - lcd.print ("I"); - lcd.setCursor (cursor, 0); - calcular_val = 1; - calcular = 1; - } - if (digitalRead(Boton_Down) == LOW) - { - delay(boton_retardo); // esperar a estabilidad - lcd.print ("O"); - lcd.setCursor (cursor, 0); - calcular_val = 0; - calcular = 1; - } - if (calcular == 1) - { - calcular = 0; - // agregar a la matriz el valor nuevo - switch (cursor) - { - case 5: // 1 - valor_Bin [1] = calcular_val; - break; - case 6: // 2 - valor_Bin [2] = calcular_val; - break; - case 7: // 4 - valor_Bin [3] = calcular_val; - break; - case 8: // 8 - valor_Bin [4] = calcular_val; - break; - case 9: // 16 - valor_Bin [5] = calcular_val; - break; - case 10: // 32 - valor_Bin [6] = calcular_val; - break; - case 11: // 64 - valor_Bin [7] = calcular_val; - break; - case 12: // 128 - valor_Bin [8] = calcular_val; - break; - case 13: // 256 - valor_Bin [9] = calcular_val; - break; - } - // calcular valor de binario a decimal - valor = 0; - if (valor_Bin [1] == 1) - { - valor = valor + 1; - } - if (valor_Bin [2] == 1) - { - valor = valor + 2; - } - if (valor_Bin [3] == 1) - { - valor = valor + 4; - } - if (valor_Bin [4] == 1) - { - valor = valor + 8; - } - if (valor_Bin [5] == 1) - { - valor = valor + 16; - } - if (valor_Bin [6] == 1) - { - valor = valor + 32; - } - if (valor_Bin [7] == 1) - { - valor = valor + 64; - } - if (valor_Bin [8] == 1) - { - valor = valor + 128; - } - if (valor_Bin [9] == 1) - { - valor = valor + 256; - } - // escribir el valor en decimal - Numerico_Write (valor, 5, 3); - lcd.setCursor (cursor, 0); - } - } - delay(200); // esperar a estabilidad - lcd.noBlink(); - goto calc; - } - // Decimal a binario - if (LCD_Col_Pos == 4 && LCD_Row_Pos == 3) - { - Num_Row_Pos = 3; - Num_Col_Pos = 5; - Numerico_Calc (0); - if (Num_Val > 511) - { - Num_Val = 511; // corregir valor en pantalla - lcd.setCursor (5, 3); - lcd.print ("511"); - } - valor = Num_Val; - // escribir 00000000 en el valor binario para borrar el anterior - lcd.setCursor (5, 0); - lcd.print ("OOOOOOOOO"); - lcd.setCursor (5, 0); - // calcular binario - valor_temp = valor; - for (byte pos = 9; pos >= 1; pos --) - { - valor_resto = valor_temp % 2; - valor_temp = valor_temp / 2; - valor_Bin [pos] = valor_resto; - if (valor_resto == 0) - { - lcd.print ("O"); - } - else - { - lcd.print ("I"); - } - } - goto calc; - } -} - -void GUI_Config() -{ - Inicio: - byte Back_Light_Value = EEPROM.read(BackLight_Add); - byte Contrast_Value = EEPROM.read(Contrast_Add); - byte Bank_Init_Value = EEPROM.read(Bank_Init_Add); - byte Key_Light_Value = EEPROM.read(Key_Light_Add); - // GUI - lcd.clear (); - lcd.setCursor (0, 0); - lcd.print (" KeyLight:"); - Numerico_Write(Key_Light_Value, 11, 0); - lcd.setCursor (15, 2); - lcd.print ("About"); - lcd.setCursor (0, 1); - lcd.print ("BackLight:"); - Numerico_Write(Back_Light_Value, 11, 1); - lcd.setCursor (1, 2); - lcd.print ("Contrast:"); - Numerico_Write(Contrast_Value, 11, 2); - lcd.setCursor (15, 3); - lcd.print ("Exit"); - // Bank - lcd.setCursor (1, 3); - lcd.print ("BankInit:"); - if (Bank_Init_Value > 8 || Bank_Init_Value < 1) - { - lcd.setCursor (11, 3); - lcd.print ("---"); - } - else - { - Numerico_Write(Bank_Init_Value, 11, 3); - } - // Cursor - LCD_Col_Pos = 10; // posicion de cursor - LCD_Row_Pos = 1; // posicion de cursor - // configuracion de cursor - Cursor_Conf_Clear(); // limpiar array - // Cursores - Cursor_Conf[1][10] = 1; // Back Light Value - Cursor_Conf[2][10] = 1; // Contrast Value - Cursor_Conf[3][10] = 1; // Bank init Value - Cursor_Conf[0][10] = 1; // Key Light Value - Cursor_Conf[3][14] = 1; // Exit - Cursor_Conf[2][14] = 1; // About - Navegacion: - GUI_Navegar(0, 0); - // Acciones - //Back Light Value - if (LCD_Col_Pos == 10 && LCD_Row_Pos == 1) - { - Num_Row_Pos = 1; - Num_Col_Pos = 11; - Numerico_Calc (1); - if (Num_Val == 712) - { - lcd.setCursor (10, 1); - lcd.print("a"); // indicar que es analogo - digitalWrite(Boton_Array_3, LOW); // lectura linea 3 - lcd.blink(); - while (digitalRead(Boton_Array_D) == HIGH && digitalRead(Boton_Center) == HIGH) // enter y center para paro - { - Num_Val = analogRead(Pot); // lectura desde el potenciometro - Num_Val = Num_Val / 4; // / 4 porque es de 12 bits - Numerico_Write(Num_Val, 11, 1); - analogWrite(Back_Light_PWM, Num_Val); - delay(50); // retardo de lectura - } - lcd.noBlink(); - digitalWrite(Boton_Array_3, HIGH); // lectura linea 3 - delay(300); // retraso para center - goto salida; - } - if (Num_Val > 255) - { - Num_Val = 255; - Numerico_Write (255, 11, 1); - } - analogWrite(Back_Light_PWM, Num_Val); - salida: - // mecanismo para on off Enable - if (Num_Val == 0) - { - Light_On_Off = 0; - } - if (Num_Val > 0) - { - Light_On_Off = 1; - } - EEPROM.write(BackLight_Add, Num_Val); // guardar valor nuevo - goto Navegacion; - } - //Key Light Value - if (LCD_Col_Pos == 10 && LCD_Row_Pos == 0) - { - Num_Row_Pos = 0; - Num_Col_Pos = 11; - Numerico_Calc (1); - if (Num_Val == 712) - { - lcd.setCursor (10, 0); - lcd.print("a"); // indicar que es analogo - digitalWrite(Boton_Array_3, LOW); // lectura linea 3 - lcd.blink(); - while (digitalRead(Boton_Array_D) == HIGH && digitalRead(Boton_Center) == HIGH) // enter y center para paro - { - Num_Val = analogRead(Pot); // lectura desde el potenciometro - Num_Val = Num_Val / 4; // / 4 porque es de 12 bits - Numerico_Write(Num_Val, 11, 0); - analogWrite(Key_Light_PWM, Num_Val); - delay(50); // retardo de lectura - } - lcd.noBlink(); - digitalWrite(Boton_Array_3, HIGH); // lectura linea 3 - delay(300); // retraso para center - goto salida_key; - } - if (Num_Val > 255) - { - Num_Val = 255; - Numerico_Write (255, 11, 0); - } - analogWrite(Key_Light_PWM, Num_Val); - salida_key: - // mecanismo para on off Enable - if (Num_Val == 0) - { - Light_On_Off = 0; - } - if (Num_Val > 0) - { - Light_On_Off = 1; - } - EEPROM.write(Key_Light_Add, Num_Val); // guardar valor nuevo - goto Navegacion; - } - //Contrast Value - if (LCD_Col_Pos == 10 && LCD_Row_Pos == 2) - { - Num_Row_Pos = 2; - Num_Col_Pos = 11; - Numerico_Calc (1); - if (Num_Val == 712) - { - lcd.setCursor (10, 2); - lcd.print("a"); // indicar que es analogo - digitalWrite(Boton_Array_3, LOW); // lectura linea 3 - lcd.blink(); - while (digitalRead(Boton_Array_D) == HIGH && digitalRead(Boton_Center) == HIGH) // enter y center para paro - { - Num_Val = analogRead(Pot); // lectura desde el potenciometro - Num_Val = Num_Val / 4; // / 4 porque es de 12 bits - if (Num_Val > 149) // limite menor de contraste LCD - { - Numerico_Write(Num_Val, 11, 2); - analogWrite(Contrast_PWM, Num_Val); - } - if (Num_Val < 149) - { - Numerico_Write(150, 11, 2); - } - delay(50); // retardo de lectura - } - lcd.noBlink(); - digitalWrite(Boton_Array_3, HIGH); // lectura linea 3 - delay(300); // retraso para center - goto salir; - } - if (Num_Val > 255) - { - Num_Val = 255; - Numerico_Write (255, 11, 2); - } - if (Num_Val < 150) - { - Num_Val = 150; // limite menor de contraste LCD - Numerico_Write (150, 11, 2); - } - analogWrite(Contrast_PWM, Num_Val); - salir: - EEPROM.write(Contrast_Add, Num_Val); // guardar valor nuevo - goto Navegacion; - } - //Bank init Value - if (LCD_Col_Pos == 10 && LCD_Row_Pos == 3) - { - Num_Row_Pos = 3; - Num_Col_Pos = 11; - Numerico_Calc (1); - if (Num_Val > 8) - { - Num_Val = 8; - Numerico_Write (8, 11, 3); - } - if (Num_Val == 0) - { - lcd.setCursor (11, 3); - lcd.print("---"); - } - EEPROM.write(Bank_Init_Add, Num_Val); // guardar valor nuevo - goto Navegacion; - } - // Exit - if (LCD_Col_Pos == 14 && LCD_Row_Pos == 3) - { - GUI_Control_Options(); - goto Navegacion; - } - // About - if (LCD_Col_Pos == 14 && LCD_Row_Pos == 2) - { - GUI_About(); - GUI_Licence(); - goto Inicio; - } - goto Navegacion; -} - -void GUI_Control_Multiply() -{ - int First_Channel = 1; - long Multiply = 0; - long Quantity = 0; - int Value = 255; - iniciar: - // LCD - lcd.clear (); - lcd.setCursor (0, 0); - lcd.print ("b Value"); - lcd.setCursor (1, 0); - if (Universo_Actual == 0) - { - lcd.print("-"); - } - else - { - lcd.print(Universo_Actual); - } - lcd.setCursor (0, 1); - lcd.print ("First CH Exit"); - lcd.setCursor (0, 2); - lcd.print ("Multiply Memory"); - lcd.setCursor (0, 3); - lcd.print ("Quantity Apply"); - Numerico_Write (Value, 9, 0); - Numerico_Write (First_Channel, 9, 1); - Numerico_Write (Multiply, 9, 2); - Numerico_Write (Quantity, 9, 3); - // Cursor - LCD_Col_Pos = 8; // posicion de cursor - LCD_Row_Pos = 0; - Siguiente: - // configuracion de cursor - Cursor_Conf_Clear(); // limpiar array - // Acciones - Cursor_Conf[1][8] = 1; // first Channel - Cursor_Conf[3][8] = 1; // quantity - Cursor_Conf[2][8] = 1; // Multiply - Cursor_Conf[1][13] = 1; // control - Cursor_Conf[2][13] = 1; // Memory - Cursor_Conf[3][13] = 1; // apply - Cursor_Conf[0][8] = 1; // value - // navegar - GUI_Navegar(0, 0); - // Acciones - // Exit - if (LCD_Col_Pos == 13 && LCD_Row_Pos == 1) - { - GUI_Control_Options(); - } - // Memory - if (LCD_Col_Pos == 13 && LCD_Row_Pos == 2) - { - GUI_Memory(); - goto iniciar; - } - // Apply - if (LCD_Col_Pos == 13 && LCD_Row_Pos == 3) - { - // Validar datos - long valid = Multiply * Quantity; - if (valid > 512) // si no es valido - { - lcd.setCursor(13, 0); - lcd.print("Error! "); - goto Siguiente; - } - // calcular - lcd.setCursor(13, 0); - lcd.print(" "); - lcd.setCursor(14, 3); - lcd.print("Calc.."); - long canal; - for (long conteo = 1; conteo <= Quantity; conteo++) - { - if (conteo == 1) - { - canal = First_Channel; - } - if (conteo != 1) - { - canal = canal + Multiply; - } - if (canal > 512) - { - canal = canal - Multiply; - conteo = Quantity; - } - lcd.setCursor(17, 0); - lcd.print(canal); - delay (5); - ArduinoDmx0.TxBuffer[canal - 1] = Value; - DMX_Values[canal] = Value; - } - lcd.setCursor(13, 0); - lcd.print("Ok!"); - lcd.setCursor(14, 3); - lcd.print("Apply "); - goto Siguiente; - } - // First Channel - if (LCD_Col_Pos == 8 && LCD_Row_Pos == 1) - { - Num_Row_Pos = 1; - Num_Col_Pos = 9; - Num_Val = First_Channel; // para dejar el numero que estaba si no se cambia - Numerico_Calc(0); - First_Channel = Num_Val; - if (First_Channel == 0) - { - First_Channel = 1; - Numerico_Write (First_Channel, 9, 1); - } - if (First_Channel > 512) - { - First_Channel = 512; - Numerico_Write (First_Channel, 9, 1); - } - } - // Multiply - if (LCD_Col_Pos == 8 && LCD_Row_Pos == 2) - { - Num_Row_Pos = 2; - Num_Col_Pos = 9; - Num_Val = Multiply; // para dejar el numero que estaba si no se cambia - Numerico_Calc(0); - Multiply = Num_Val; - if (Multiply == 0) - { - Multiply = 1; - Numerico_Write (Multiply, 9, 2); - } - if (Multiply > 512) - { - Multiply = 512; - Numerico_Write (Multiply, 9, 2); - } - } - // Quantity - if (LCD_Col_Pos == 8 && LCD_Row_Pos == 3) - { - Num_Row_Pos = 3; - Num_Col_Pos = 9; - Num_Val = Quantity; // para dejar el numero que estaba si no se cambia - Numerico_Calc(0); - Quantity = Num_Val; - if (Quantity == 0) - { - Quantity = 1; - Numerico_Write (Quantity, 9, 3); - } - if (Quantity > 512) - { - Quantity = 512; - Numerico_Write (Quantity, 9, 3); - } - } - // Value - if (LCD_Col_Pos == 8 && LCD_Row_Pos == 0) - { - Num_Row_Pos = 0; - Num_Col_Pos = 9; - Num_Val = Value; // para dejar el numero que estaba si no se cambia - Numerico_Calc(1); - Value = Num_Val; - if (Value > 255) - { - Value = 255; - Numerico_Write (Value, 9, 0); - } - } - goto Siguiente; -} - -void GUI_Control_Chaser() -{ - long Delay = 1; - long First = 1; - long Final = 0; - // LCD - lcd.clear (); - lcd.setCursor (0, 0); - lcd.print ("ChaserCH ---"); - lcd.setCursor (3, 1); - lcd.print ("Delay x10=mS"); - lcd.setCursor (0, 2); - lcd.print ("First CH Exit"); - lcd.setCursor (0, 3); - lcd.print ("Final CH Start"); - Numerico_Write (Delay, 9, 1); - Numerico_Write (First, 9, 2); - Numerico_Write (Final, 9, 3); - // Cursor - LCD_Col_Pos = 8; // posicion de cursor - LCD_Row_Pos = 1; - Siguiente: - // configuracion de cursor - Cursor_Conf_Clear(); // limpiar array - // Acciones - Cursor_Conf[1][8] = 1; // Delay - Cursor_Conf[2][8] = 1; // First - Cursor_Conf[3][8] = 1; // Final - Cursor_Conf[2][14] = 1; // control - Cursor_Conf[3][14] = 1; // Start - // navegar - GUI_Navegar(0, 0); - // Acciones - // Control - if (LCD_Col_Pos == 14 && LCD_Row_Pos == 2) - { - // regresar el universo a su lugar - for(int Canal = 1; Canal <= 512; Canal ++) - { - ArduinoDmx0.TxBuffer[Canal - 1] = DMX_Values[Canal]; - } - GUI_Control_Options(); - } - // Start - if (LCD_Col_Pos == 14 && LCD_Row_Pos == 3) - { - long ciclo_longitud = 1300; // numero multiplicador aprox para 1 seg - long ciclo = 0; - long Delay_Cont = 0; - int canal = First; - lcd.setCursor(15,3); - lcd.print("Stop "); - lcd.blink(); - // borrar canales previos - for(int Canales = 0; Canales <= 512; Canales ++) - { - ArduinoDmx0.TxBuffer[Canales] = 0; // salida a DMX - } - while (digitalRead(Boton_Center) == HIGH) // lectura del boton centro - { - ciclo = ciclo + 1; - if (ciclo == ciclo_longitud) - { - Delay_Cont = Delay_Cont + 1; - if (Delay_Cont == Delay) - { - if (canal > Final) - { - canal = First; - } - Numerico_Write (canal, 9, 0); - lcd.setCursor(19,3); - // apagar lo anterior - for (long contar = First; contar <= Final; contar ++) - { - ArduinoDmx0.TxBuffer[contar - 1] = 0; - } - // encender el siguiente - ArduinoDmx0.TxBuffer[canal - 1] = 255; - Delay_Cont = 0; - canal = canal + 1; - } - ciclo = 0; - } - } - lcd.noBlink(); - lcd.setCursor(15,3); - lcd.print("Start"); - delay (300); // evita que le gane la descarga del capacitor - goto Siguiente; - } - // Delay - if (LCD_Col_Pos == 8 && LCD_Row_Pos == 1) - { - Num_Row_Pos = 1; - Num_Col_Pos = 9; - Num_Val = Delay; // para dejar el numero que estaba si no se cambia - Numerico_Calc(0); - Delay = Num_Val; - } - // First - if (LCD_Col_Pos == 8 && LCD_Row_Pos == 2) - { - Num_Row_Pos = 2; - Num_Col_Pos = 9; - Num_Val = First; // para dejar el numero que estaba si no se cambia - Numerico_Calc(0); - First = Num_Val; - if (First == 0) - { - First = 1; - Numerico_Write (First, 9, 2); - } - if (First > 512) - { - First = 512; - Numerico_Write (First, 9, 2); - } - } - // Final - if (LCD_Col_Pos == 8 && LCD_Row_Pos == 3) - { - Num_Row_Pos = 3; - Num_Col_Pos = 9; - Num_Val = Final; // para dejar el numero que estaba si no se cambia - Numerico_Calc(0); - Final = Num_Val; - if (Final == 0) - { - Final = 1; - Numerico_Write (Final, 9, 3); - } - if (Final > 512) - { - Final = 512; - Numerico_Write (Final, 9, 3); - } - } - goto Siguiente; -} - -void Numerico_Write (int valor, int col, int row) -{ - // posicionar el valor en los campos 000 - lcd.setCursor (col, row); - lcd.print ("000"); - if (valor < 10) - { - lcd.setCursor (col + 2, row); - } - if (valor > 9 && valor < 100) - { - lcd.setCursor (col + 1, row); - } - if (valor > 99) - { - lcd.setCursor (col, row); - } - lcd.print (valor); -} - -void GUI_Control_Unit() -{ - Inicio: - Canal_Actual = 1; - // GUI - lcd.clear (); - lcd.setCursor (0, 0); - lcd.print ("Unitary Control: b"); - if (Universo_Actual == 0) - { - lcd.print("-"); - } - else - { - lcd.print(Universo_Actual); - } - lcd.setCursor (14, 2); - lcd.print ("Exit"); - lcd.setCursor (14, 3); - lcd.print ("Memory"); - lcd.setCursor (0, 2); - lcd.print ("Channel: 001"); - lcd.setCursor (2, 3); - lcd.print ("Value:"); - Numerico_Write(DMX_Values[1], 9, 3); - lcd.setCursor (0, 1); - lcd.print ("c002=v"); - Numerico_Write(DMX_Values[2], 6, 1); - lcd.setCursor (11, 1); - lcd.print ("c003=v"); - Numerico_Write(DMX_Values[3], 17, 1); - // Cursor - LCD_Col_Pos = 8; // posicion de cursor - LCD_Row_Pos = 2; // posicion e cursor - // configuracion de cursor - Cursor_Conf_Clear(); // limpiar array - // Cursores - Cursor_Conf[2][8] = 1; // Channel - Cursor_Conf[3][8] = 1; // Value - Cursor_Conf[2][13] = 1; // Control - Cursor_Conf[3][13] = 1; // Memory - // navegar - Navegacion: - GUI_Navegar(0, 0); - // Acciones - //Channel - if (LCD_Col_Pos == 8 && LCD_Row_Pos == 2) - { - Numerico_Write(Canal_Actual, 9, 2); - Num_Row_Pos = 2; - Num_Col_Pos = 9; - Num_Val = Canal_Actual; // para dejar el numero que estaba si no se cambia - Numerico_Calc (0); - if (Num_Val > 512) - { - Num_Val = 512; - Numerico_Write (512, 9, 2); - } - if (Num_Val < 1) - { - Num_Val = 1; - Numerico_Write (1, 9, 2); - } - // mostrar valor actual del canal - Canal_Actual = Num_Val; - Numerico_Write(DMX_Values[Canal_Actual], 9, 3); - // mostrar anterior y siguiente - if (Canal_Actual == 1) - { - Numerico_Write(2, 1, 1); - Numerico_Write(DMX_Values[2], 6, 1); - Numerico_Write(3, 12, 1); - Numerico_Write(DMX_Values[3], 17, 1); - } - if (Canal_Actual == 512) - { - Numerico_Write(510, 1, 1); - Numerico_Write(DMX_Values[510], 6, 1); - Numerico_Write(511, 12, 1); - Numerico_Write(DMX_Values[511], 17, 1); - } - if (Canal_Actual > 1 && Canal_Actual < 512) - { - Numerico_Write(Canal_Actual - 1, 1, 1); - Numerico_Write(DMX_Values[Canal_Actual - 1], 6, 1); - Numerico_Write(Canal_Actual + 1, 12, 1); - Numerico_Write(DMX_Values[Canal_Actual + 1], 17, 1); - } - } - // Value - if (LCD_Col_Pos == 8 && LCD_Row_Pos == 3) - { - Num_Row_Pos = 3; - Num_Col_Pos = 9; - Num_Val = DMX_Values[Canal_Actual]; // para dejar el numero que estaba si no se cambia - Numerico_Calc (1); - if (Num_Val == 612) // ubicar - { - Ubicar(); - } - if (Num_Val == 712) // analogo - { - Analog_Read_DMX(9, 3); - goto Navegacion; - } - if (Num_Val > 255) - { - Num_Val = 255; - Numerico_Write (255, 9, 3); - } - // Escribr valor en dmx - ArduinoDmx0.TxBuffer[Canal_Actual - 1] = Num_Val; - DMX_Values[Canal_Actual] = Num_Val; - goto Navegacion; - } - // Memory - if (LCD_Col_Pos == 13 && LCD_Row_Pos == 3) - { - GUI_Memory(); - goto Inicio; - } - // Control - if (LCD_Col_Pos == 13 && LCD_Row_Pos == 2) - { - GUI_Control_Options(); - } - goto Navegacion; -} - -void Ubicar() -{ - digitalWrite(Boton_Array_4, LOW); - while (digitalRead(Boton_Array_C) == HIGH && digitalRead(Boton_Center) == HIGH) - { - ArduinoDmx0.TxBuffer[Canal_Actual - 1] = 255; - Numerico_Write (255, Num_Col_Pos - 2, Num_Row_Pos); - delay (100); - ArduinoDmx0.TxBuffer[Canal_Actual - 1] = 0; - lcd.setCursor (Num_Col_Pos - 2, Num_Row_Pos); - lcd.print (" "); - delay (100); - } - digitalWrite(Boton_Array_4, HIGH); - delay(300); // rebote de boton enter - lcd.setCursor (Num_Col_Pos, Num_Row_Pos); -} - -void Numerico_Calc(byte value) -{ - // escritura del numero desde el teclado numerico si value es 1 entra opcion de A 255 y B 0 - int Num_Val_Temp_1 = 0; - int Num_Val_Temp_2 = 0; - lcd.setCursor (Num_Col_Pos, Num_Row_Pos); - lcd.print("___"); - lcd.blink(); // mostrar cursor - //Num_Val = 0; - Num_Col_Pos = Num_Col_Pos + 2; - lcd.setCursor (Num_Col_Pos, Num_Row_Pos); - // primer numero - Numerico_Read(); // leer boton - if (Boton_Calc <= 9) - { - lcd.print (Boton_Calc); // escribir valor calculado - lcd.setCursor (Num_Col_Pos, Num_Row_Pos); - Num_Val = Boton_Calc; // valor calculado - Num_Val_Temp_1 = Boton_Calc; // valor temporal para el acarreo - } - if (Boton_Calc == 14) // enter - { - goto Salida; // num val = 0 - } - if (value == 1) // si es un valor - { - if (Boton_Calc == 10) // 255 - { - Num_Val = 255; - goto Salida; - } - if (Boton_Calc == 11) // 000 - { - Num_Val = 0; - goto Salida; - } - if (Boton_Calc == 12) // ubicar - { - Num_Val = 612; - goto Salida_Option; - } - if (Boton_Calc == 13) // analogo - { - Num_Val = 712; - goto Salida_Option; - } - } - // segundo numero - Numerico_Read(); // leer boton - if (Boton_Calc == 14) // enter - { - Num_Val = Num_Val_Temp_1; - goto Salida; // num val = num val anterior - } - if (value == 1) // si es un valor - { - if (Boton_Calc == 10) // 255 - { - Num_Val = 255; - goto Salida; - } - if (Boton_Calc == 11) // 000 - { - Num_Val = 0; - goto Salida; - } - if (Boton_Calc == 12) // ubicar - { - Num_Val = 612; - goto Salida_Option; - } - if (Boton_Calc == 13) // analogo - { - Num_Val = 712; - goto Salida_Option; - } - } - if (Boton_Calc <= 9) - { - // recorrer numero ya impreso - Num_Col_Pos = Num_Col_Pos - 1; - lcd.setCursor (Num_Col_Pos, Num_Row_Pos); - lcd.print (Num_Val_Temp_1); - // dibujar numero nuevo - lcd.print (Boton_Calc); - Num_Val_Temp_2 = Boton_Calc; - Num_Col_Pos = Num_Col_Pos + 1; - lcd.setCursor (Num_Col_Pos, Num_Row_Pos); - } - // Tercer numero - Numerico_Read(); // leer boton - if (Boton_Calc == 14) // enter - { - Num_Val = (Num_Val_Temp_1 * 10) + Num_Val_Temp_2; - goto Salida; - } - if (value == 1) // si es un valor - { - if (Boton_Calc == 10) // 255 - { - Num_Val = 255; - goto Salida; - } - if (Boton_Calc == 11) // 000 - { - Num_Val = 0; - goto Salida; - } - if (Boton_Calc == 12) // ubicar - { - Num_Val = 612; - goto Salida_Option; - } - if (Boton_Calc == 13) // analogo - { - Num_Val = 712; - goto Salida_Option; - } - } - if (Boton_Calc <= 9) - { - // recorrer numero ya impreso - Num_Col_Pos = Num_Col_Pos - 2; - lcd.setCursor (Num_Col_Pos, Num_Row_Pos); - lcd.print (Num_Val_Temp_1); - lcd.print (Num_Val_Temp_2); - // dibujar numero nuevo - Num_Col_Pos = Num_Col_Pos + 2; - lcd.setCursor (Num_Col_Pos, Num_Row_Pos); - lcd.print (Boton_Calc); - Num_Val = Boton_Calc + (Num_Val_Temp_1 * 100) + (Num_Val_Temp_2 * 10); - } - Salida: - lcd.noBlink(); - // pintar los ceros antes del numero - Numerico_Write (Num_Val, Num_Col_Pos - 2, Num_Row_Pos); - Num_Col_Pos = Num_Col_Pos - 4; - // regresar el cursor a su ligar - lcd.setCursor (Num_Col_Pos, Num_Row_Pos); - Salida_Option: - { - lcd.noBlink(); - lcd.setCursor (Num_Col_Pos, Num_Row_Pos); - delay(300); // rebote de boton - } -} - -void Numerico_Read() -{ - long Num_Barrido_Time = 5; // tiempo entre barrido de keys - Boton_Calc = 17; // limpiar valor para lectura - while (Boton_Calc == 17) // valor calculado # E * F, 17 sin valor calculado - { - // Barrido - // Linea 1 - digitalWrite(Boton_Array_1, LOW); // lectura linea 1 - // Lectura 1A = 1 - if (digitalRead(Boton_Array_A) == LOW) - { - Boton_Calc = 1; - delay(Boton_Delay_Teclado); - } - delay(Num_Barrido_Time); - // Lectura 1B = 6 - if (digitalRead(Boton_Array_B) == LOW) - { - Boton_Calc = 4; - delay(Boton_Delay_Teclado); - } - delay(Num_Barrido_Time); - // Lectura 1C = 7 - if (digitalRead(Boton_Array_C) == LOW) - { - Boton_Calc = 7; - delay(Boton_Delay_Teclado); - } - delay(Num_Barrido_Time); - // Lectura 1D = * = 15 - if (digitalRead(Boton_Array_D) == LOW) - { - Boton_Calc = 15; - delay(Boton_Delay_Teclado); - } - delay(Num_Barrido_Time); - digitalWrite(Boton_Array_1, HIGH); // lectura linea 1 - - // Linea 2 - digitalWrite(Boton_Array_2, LOW); // lectura linea 2 - // Lectura 2A = 2 - if (digitalRead(Boton_Array_A) == LOW) - { - Boton_Calc = 2; - delay(Boton_Delay_Teclado); - } - delay(Num_Barrido_Time); - // Lectura 2B = 5 - if (digitalRead(Boton_Array_B) == LOW) - { - Boton_Calc = 5; - delay(Boton_Delay_Teclado); - } - delay(Num_Barrido_Time); - // Lectura 2C = 8 - if (digitalRead(Boton_Array_C) == LOW) - { - Boton_Calc = 8; - delay(Boton_Delay_Teclado); - } - delay(Num_Barrido_Time); - // Lectura 2D = 0 - if (digitalRead(Boton_Array_D) == LOW) - { - Boton_Calc = 0; - delay(Boton_Delay_Teclado); - } - delay(Num_Barrido_Time); - digitalWrite(Boton_Array_2, HIGH); // lectura linea 2 - - // Linea 3 - digitalWrite(Boton_Array_3, LOW); // lectura linea 3 - // Lectura 3A = 3 - if (digitalRead(Boton_Array_A) == LOW) - { - Boton_Calc = 3; - delay(Boton_Delay_Teclado); - } - delay(Num_Barrido_Time); - // Lectura 3B = 4 - if (digitalRead(Boton_Array_B) == LOW) - { - Boton_Calc = 6; - delay(Boton_Delay_Teclado); - } - delay(Num_Barrido_Time); - // Lectura 3C = 9 - if (digitalRead(Boton_Array_C) == LOW) - { - Boton_Calc = 9; - delay(Boton_Delay_Teclado); - } - delay(Num_Barrido_Time); - // Lectura 3D = 14 - if (digitalRead(Boton_Array_D) == LOW) - { - Boton_Calc = 14; - delay(Boton_Delay_Teclado); - } - delay(Num_Barrido_Time); - digitalWrite(Boton_Array_3, HIGH); // lectura linea 3 - - // Linea 4 - digitalWrite(Boton_Array_4, LOW); // lectura linea 4 - // Lectura 4A = 10 - if (digitalRead(Boton_Array_A) == LOW) - { - Boton_Calc = 10; - delay(Boton_Delay_Teclado); - } - delay(Num_Barrido_Time); - // Lectura 4B = 11 - if (digitalRead(Boton_Array_B) == LOW) - { - Boton_Calc = 11; - delay(Boton_Delay_Teclado); - } - delay(Num_Barrido_Time); - // Lectura 4C = 12 - if (digitalRead(Boton_Array_C) == LOW) - { - Boton_Calc = 12; - delay(Boton_Delay_Teclado); - } - delay(Num_Barrido_Time); - // Lectura 4D = 13 - if (digitalRead(Boton_Array_D) == LOW) - { - Boton_Calc = 13; - delay(Boton_Delay_Teclado); - } - delay(Num_Barrido_Time); - digitalWrite(Boton_Array_4, HIGH); // lectura linea 4 - - // Cursor center "enter" - if (digitalRead(Boton_Center) == LOW) - { - Boton_Calc = 14; - delay(Boton_Delay_Teclado); - } - } -} - -void Analog_Read_DMX(byte col, byte row) -{ - // escritura del numero desde el potenciometro aplica a dmx - int read; - lcd.setCursor (col - 1, row); - lcd.print("a"); // indicar que es analogo - digitalWrite(Boton_Array_3, LOW); // lectura linea 3 - lcd.blink(); - int valores = 0; - while (digitalRead(Boton_Array_D) == HIGH && digitalRead(Boton_Center) == HIGH) // enter y center para paro - { - read = analogRead(Pot); // lectura desde el potenciometro - read = read / 4; // / 4 porque es de 12 bits - delay(50); - if (valores != read) - { - Numerico_Write(read, col, row); - lcd.setCursor (col + 2, row); - ArduinoDmx0.TxBuffer[Canal_Actual - 1] = read; - DMX_Values[Canal_Actual] = read; - valores = read; - } - } - lcd.noBlink(); - digitalWrite(Boton_Array_3, HIGH); // lectura linea 3 - delay(300); // delay para salir de la lectura analoga -} - +// *************************************************************************************************************************** +// *************************************************************************************************************************** +// ** ** +// ** Arduino DMX-512 Tester Controller ** +// ** ** +// ** - Firmware v1.6 ** +// ** - Hardware v0.4 ** +// ** ** +// ** - Compilado en Arduino IDE v1.0.6 ** +// ** - Editado en Notepad++ ** +// ** http://www.arduino.cc/en/Main/OldSoftwareReleases ** +// ** Formato Windows ANSI ** +// ** - Compilado para Arduino Mega 2560 R3 ** +// ** http://www.arduino.cc/en/Main/ArduinoBoardMega2560 ** +// ** - Libreria Arduino cuatro universos DMX v0.3 - Deskontrol.net ** +// ** http://www.deskontrol.net/blog/libreria-arduino-cuatro-universos-dmx/) ** +// ** - Libreria LCD v1.2.1 - Francisco Malpartida ** +// ** https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home ** +// ** - Libreria Encoder v1.2 - www.pjrc.com ** +// ** http://www.pjrc.com/teensy/td_libs_Encoder.html ** +// ** - Simulacion en Proteus v7.7 SP2 ** +// ** - Simulacion en Proteus de Arduino - Microcontrolandos ** +// ** http://microcontrolandos.blogspot.mx/2012/12/arduino-componentes-para-o-proteus.html ** +// ** ** +// ** Autor: ** +// ** ** +// ** Copyright (C) 2015 - Daniel Roberto Becerril Angeles ** +// ** daniel3514@gmail.com ** +// ** https://github.com/daniel3514/Arduino-DMX-512-Tester-Controller/wiki ** +// ** ** +// ** Licenciamiento: ** +// ** ** +// ** Firmware: ** +// ** GNU General Pubic Licence Version v3 ** +// ** https://www.gnu.org/copyleft/gpl.html ** +// ** ** +// ** Hardware: ** +// ** Open Source Hardware (OSHW) v1.0 ** +// ** http://freedomdefined.org/OSHW#Licenses_and_Hardware ** +// ** http://www.oshwa.org/definition/ ** +// ** ** +// ** Este programa es software libre: usted puede redistribuirlo y / o modificarlo bajo los términos de la ** +// ** Licencia Pública General GNU publicada por la Free Software Foundation, bien de la versión 3 de la Licencia, ** +// ** o (A su elección) cualquier versión posterior. ** +// ** ** +// ** Este programa se distribuye con la esperanza de que sea útil, pero SIN NINGUNA GARANTIA; ni siquiera la garantía ** +// ** implícita de COMERCIALIZACION o IDONEIDAD PARA UN PROPOSITO PARTICULAR. Vea el GNU General Public License ** +// ** para más detalles. ** +// ** ** +// ** Esto es software libre, y le invitamos a redistribuirlo bajo ciertas condiciones ** +// ** ** +// ** Deberá haber recibido una copia de la Licencia Pública General GNU ** +// ** junto con este programa. Si no es así, consulte . ** +// ** ** +// *************************************************************************************************************************** +// *************************************************************************************************************************** + +// Librerias +#include // libreria para LCD - ttps://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home +#include +#include +#include +#include // libreria DMX 4 universos deskontrol four universes DMX library - http://www.deskontrol.net/blog +#include // libreria encoder - http://www.pjrc.com/teensy/td_libs_Encoder.html + +// DMX Library +#define DMX512 (0) // (250 kbaud - 2 to 512 channels) Standard USITT DMX-512 +//#define DMX1024 (1) // (500 kbaud - 2 to 1024 channels) Completely non standard - TESTED ok +//#define DMX2048 (2) // (1000 kbaud - 2 to 2048 channels) called by manufacturers DMX1000K, DMX 4x or DMX 1M ??? + +// Puertos, variables +// DMX +int DMX_Data_Flux = 2; // control de flujo de datos para dmx, 0 por default +int DMX_Values [515]; // array de valores actuales DMX +int Canal_Actual = 1; +byte Universo_Actual = 0; +// Encoder +Encoder myEnc(7, 6); // coneccion de encoder +// Botones cursor +int Boton_Up = 9; +int Boton_Down = 12; +int Boton_Left = 8; +int Boton_Right = 10; +int Boton_Center = 11; +byte LCD_Col_Pos = 0; // posicion en tiempo real de lcd +byte LCD_Row_Pos = 0; // posicion en tiempo real de lcd +// config de posiciones de lcd Col Row +byte Cursor_Conf[4][20] = { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +}; +// Botones Numerico Array +int Boton_Array_1 = 38; +int Boton_Array_2 = 40; +int Boton_Array_3 = 42; +int Boton_Array_4 = 44; +int Boton_Array_A = 30; +int Boton_Array_B = 32; +int Boton_Array_C = 34; +int Boton_Array_D = 36; +byte Boton_Calc = 17; // valor calculado # E * F, 17 sin valor calculado +byte Num_Col_Pos = 0; // posicion en tiempo real de lcd +byte Num_Row_Pos = 0; // posicion en tiempo real de lcd +int Num_Val = 0; // valor generado al calculo +long Boton_Delay_Teclado = 100; // delay de lectura de boton +// Potenciometro +int Pot = A15; // entrada de potenciometro +// LCD +int LCD_RS = 43; // puertos de conexion de LCD +int LCD_E = 45; +int LCD_D4 = 47; +int LCD_D5 = 49; +int LCD_D6 = 51; +int LCD_D7 = 53; +LiquidCrystal lcd(LCD_RS, LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7); //LCD setup +int Back_Light_PWM = 13; // salida para PWM de Back Light de LCD +int Contrast_PWM = 4; // salida para pwm de contraste de LCD +byte Light_On_Off = 0; // saber si esta encendida o apagada, back y key +// Key Light +int Key_Light_PWM = 3; // salida para pwm de key light +// EEPROM +int BackLight_Add = 4094; // direccion de eeprom +int Contrast_Add = 4095; // direccion de eeprom +int Bank_Init_Add = 4093; // direccion de eeprom +int Key_Light_Add = 4092; // direccion de eeprom +int EEPROM_Limit = 4091; // limite de espacios en eeprom para universos + +void setup() +{ + // DMX + // pinMode(DMX_Data_Flux, OUTPUT); + // Botones cursor + pinMode(Boton_Up, INPUT_PULLUP); + pinMode(Boton_Down, INPUT_PULLUP); + pinMode(Boton_Left, INPUT_PULLUP); + pinMode(Boton_Right, INPUT_PULLUP); + pinMode(11, INPUT_PULLUP); //Boton_Center, INPUT_PULLUP); + // Botones numerico + pinMode(Boton_Array_1, OUTPUT); + pinMode(Boton_Array_2, OUTPUT); + pinMode(Boton_Array_3, OUTPUT); + pinMode(Boton_Array_4, OUTPUT); + pinMode(Boton_Array_A, INPUT_PULLUP); + pinMode(Boton_Array_B, INPUT_PULLUP); + pinMode(Boton_Array_C, INPUT_PULLUP); + pinMode(Boton_Array_D, INPUT_PULLUP); + digitalWrite(Boton_Array_1, HIGH); + digitalWrite(Boton_Array_2, HIGH); + digitalWrite(Boton_Array_3, HIGH); + digitalWrite(Boton_Array_4, HIGH); + // LCD + pinMode(LCD_RS, OUTPUT); + pinMode(LCD_E, OUTPUT); + pinMode(LCD_D7, OUTPUT); + pinMode(LCD_D6, OUTPUT); + pinMode(LCD_D5, OUTPUT); + pinMode(LCD_D4, OUTPUT); + pinMode(Back_Light_PWM, OUTPUT); + lcd.begin(20, 4); //tamaño de LCD + // Key Light + pinMode(Key_Light_PWM, OUTPUT); + // DMX + ArduinoDmx0.set_tx_address(1); // poner aqui la direccion de inicio de DMX + ArduinoDmx0.set_tx_channels(512); // poner aqui el numero de canales a transmitir + ArduinoDmx0.init_tx(DMX512); // iniciar transmision universo 0, modo estandar DMX512 + // no conectados + pinMode(5, OUTPUT); + digitalWrite(5, LOW); + pinMode(22, OUTPUT); + digitalWrite(22, LOW); + pinMode(23, OUTPUT); + digitalWrite(23, LOW); + pinMode(24, OUTPUT); + digitalWrite(24, LOW); + pinMode(25, OUTPUT); + digitalWrite(25, LOW); + pinMode(26, OUTPUT); + digitalWrite(26, LOW); + pinMode(27, OUTPUT); + digitalWrite(27, LOW); + pinMode(28, OUTPUT); + digitalWrite(28, LOW); + pinMode(29, OUTPUT); + digitalWrite(29, LOW); + pinMode(31, OUTPUT); + digitalWrite(31, LOW); + pinMode(33, OUTPUT); + digitalWrite(33, LOW); + pinMode(35, OUTPUT); + digitalWrite(35, LOW); + pinMode(37, OUTPUT); + digitalWrite(37, LOW); + pinMode(39, OUTPUT); + digitalWrite(39, LOW); + pinMode(41, OUTPUT); + digitalWrite(41, LOW); + pinMode(46, OUTPUT); + digitalWrite(46, LOW); + pinMode(48, OUTPUT); + digitalWrite(48, LOW); + pinMode(50, OUTPUT); + digitalWrite(50, LOW); + pinMode(52, OUTPUT); + digitalWrite(52, LOW); + pinMode(A0, OUTPUT); + digitalWrite(A0, LOW); + pinMode(A1, OUTPUT); + digitalWrite(A1, LOW); + pinMode(A2, OUTPUT); + digitalWrite(A2, LOW); + pinMode(A3, OUTPUT); + digitalWrite(A3, LOW); + pinMode(A4, OUTPUT); + digitalWrite(A4, LOW); + pinMode(A5, OUTPUT); + digitalWrite(A5, LOW); + pinMode(A6, OUTPUT); + digitalWrite(A6, LOW); + pinMode(A7, OUTPUT); + digitalWrite(A7, LOW); + pinMode(A8, OUTPUT); + digitalWrite(A8, LOW); + pinMode(A9, OUTPUT); + digitalWrite(A9, LOW); + pinMode(A10, OUTPUT); + digitalWrite(A10, LOW); + pinMode(A11, OUTPUT); + digitalWrite(A11, LOW); + pinMode(A12, OUTPUT); + digitalWrite(A12, LOW); + pinMode(A13, OUTPUT); + digitalWrite(A13, LOW); + pinMode(A14, OUTPUT); + digitalWrite(A14, LOW); +} + +void loop() +{ + digitalWrite(2, HIGH); // max 485 como salida + Back_Light_Init(); + Contrast_Init(); + EEPROM_Load_Init(); + GUI_About(); + GUI_Memory_Init(); +} + +void Back_Light_Init() +{ + // ultimo estado del back light + byte Back_Light_Value = EEPROM.read(BackLight_Add); + analogWrite(Back_Light_PWM, Back_Light_Value); + if (Back_Light_Value == 0) + { + Light_On_Off = 0; + } + if (Back_Light_Value > 0) + { + Light_On_Off = 1; + } +} + +void Key_Light_Init() +{ + // ultimo estado del Key Light + byte Key_Light_Value = EEPROM.read(Key_Light_Add); + analogWrite(Key_Light_PWM, Key_Light_Value); + if (Key_Light_Value == 0) + { + Light_On_Off = 0; + } + if (Key_Light_Value > 0) + { + Light_On_Off = 1; + } +} + +void Contrast_Init() +{ + // ultimo estado del comtrast + byte Contrast_Value = EEPROM.read(Contrast_Add); + if (Contrast_Value < 150) + { + Contrast_Value = 150; + } + analogWrite(Contrast_PWM, Contrast_Value); +} + +void Light_En() +{ + // encender back y key desde la tecla * + byte Back_Light_Value = EEPROM.read(BackLight_Add); // lectura del ultimo valor desde la eeprom + byte Key_Light_Value = EEPROM.read(Key_Light_Add); // lectura del ultimo valor desde la eeprom + long delay_dimmer = 1; + // encender + if (Light_On_Off == 0) // si esta apagada encenderla + { + // si el valor es 0 lo encendemos de todos modos + if (Back_Light_Value == 0) + { + for (int contar = 0; contar <= 127; contar ++) + { + analogWrite(Back_Light_PWM, contar); // aqui el valor a encender en el caso que se haya establecido apagado + delay(delay_dimmer); + } + } + if (Key_Light_Value == 0) + { + for (int contar = 0; contar <= 127; contar ++) + { + analogWrite(Key_Light_PWM, 127); // aqui el valor a encender en el caso que se haya establecido apagado + delay(delay_dimmer); + } + } + // solo encender + if (Back_Light_Value > 0) + { + for (int contar = 0; contar <= Back_Light_Value; contar ++) + { + analogWrite(Back_Light_PWM, contar); // encender con el valor de la eeprom + delay(delay_dimmer); + } + } + if (Key_Light_Value > 0) + { + for (int contar = 0; contar <= Back_Light_Value; contar ++) + { + analogWrite(Key_Light_PWM, Key_Light_Value);// encender con el valor de la eeprom + delay(delay_dimmer); + } + } + Light_On_Off = 1; + goto salida; + } + // apagar + if (Light_On_Off == 1) // si esta encendida apagarla + { + for (int contar = Back_Light_Value; contar != 0; contar --) + { + analogWrite(Back_Light_PWM, contar); + delay(delay_dimmer); + } + analogWrite(Back_Light_PWM, 0); + analogWrite(Key_Light_PWM, 0); + Light_On_Off = 0; + } +salida: + delay(300); // para impedir repeticion del comando +} + +void GUI_Licence() +{ + int retardo = 4000; + lcd.clear (); + lcd.setCursor(0, 0); + lcd.print(" This program is"); + lcd.setCursor(0, 1); + lcd.print("distributed in the"); + lcd.setCursor(0, 2); + lcd.print("hope that it will be"); + lcd.setCursor(0, 3); + lcd.print("useful, but"); + delay(retardo); + + lcd.clear (); + lcd.setCursor(0, 0); + lcd.print("WITHOUT ANY WARRANTY"); + lcd.setCursor(0, 1); + lcd.print("without even the"); + lcd.setCursor(0, 2); + lcd.print("implied warranty of"); + lcd.setCursor(0, 3); + lcd.print("MERCHANTABILITY of"); + delay(retardo); + + lcd.clear (); + lcd.setCursor(0, 0); + lcd.print("FITNESS FOR A"); + lcd.setCursor(0, 1); + lcd.print("PARTICULAR PORPUSE."); + lcd.setCursor(0, 2); + lcd.print(" This is free "); + lcd.setCursor(0, 3); + lcd.print("software and you are"); + delay(retardo); + + lcd.clear (); + lcd.setCursor(0, 0); + lcd.print("welcome to"); + lcd.setCursor(0, 1); + lcd.print("redistribute it"); + lcd.setCursor(0, 2); + lcd.print("under certain"); + lcd.setCursor(0, 3); + lcd.print("conditions"); + delay(retardo); + + lcd.clear (); + lcd.setCursor(0, 0); + lcd.print("See the GNU GENERAL"); + lcd.setCursor(0, 1); + lcd.print("PUBLIC LICENCE"); + lcd.setCursor(0, 2); + lcd.print("for more details..."); + delay(retardo); +} + +void GUI_About() +{ + byte Firm_Ver_Ent = 1; + byte Firm_Ver_Dec = 6; + byte Hard_Ver_Ent = 0; + byte Hard_Ver_Dec = 4; + byte Key_Light_Value = EEPROM.read(Key_Light_Add); + byte Back_Light_Value = EEPROM.read(BackLight_Add); + lcd.clear (); + analogWrite(Key_Light_PWM, 0); + analogWrite(Back_Light_PWM, 0); + for (int numero = 0; numero <= 512; numero ++) // efecto binario en lcd + { + // binario + lcd.print (numero, BIN); + // key light + if (Key_Light_Value > 0) + { + if (numero <= 255) + { + if (numero <= Key_Light_Value) + { + analogWrite(Key_Light_PWM, numero); + } + } + } + // back light + if (Back_Light_Value > 0) + { + if (numero <= 255) + { + if (numero <= Back_Light_Value) + { + analogWrite(Back_Light_PWM, numero); + } + } + } + } + lcd.clear (); + lcd.blink (); + lcd.setCursor(3, 0); + lcd.print("Arduino DMX-512"); + lcd.setCursor(1, 1); + lcd.print("Tester & Controller"); + // Firmware + lcd.setCursor(0, 3); + lcd.print("Firm v"); + lcd.print(Firm_Ver_Ent); + lcd.print("."); + lcd.print(Firm_Ver_Dec); + // Hardware + lcd.setCursor(11, 3); + lcd.print("Hard v"); + lcd.print(Hard_Ver_Ent); + lcd.print("."); + lcd.print(Hard_Ver_Dec); + // bank + lcd.setCursor(9, 2); + lcd.print("b"); + if (Universo_Actual == 0) + { + lcd.print("-"); + } + else + { + lcd.print(Universo_Actual); + } + lcd.setCursor(10, 2); // Blink + // lectura del boton centro + while (digitalRead(Boton_Center) == HIGH) + { + + } + delay (300); // rebote de boton + lcd.clear (); + lcd.setCursor(0, 0); + lcd.print("Open Source License:"); + lcd.setCursor(0, 1); + lcd.print("Firm: GNU GPL v3"); + lcd.setCursor(0, 2); + lcd.print("Hard: OSHW v1"); + lcd.setCursor(0, 3); + lcd.print("Wiki: goo.gl/5nqJKt"); + lcd.setCursor(2, 1); + // bank + lcd.setCursor(18, 1); + lcd.print("b"); + if (Universo_Actual == 0) + { + lcd.print("-"); + } + else + { + lcd.print(Universo_Actual); + } + lcd.setCursor(19, 1); + // lectura del boton centro + while (digitalRead(Boton_Center) == HIGH) + { + + } + delay (300); // rebote de boton + lcd.noBlink (); +} + +void Multi_Matrix(int inicial) +{ + // dibujar banco + Numerico_Write (inicial, 13, 0); + Numerico_Write (inicial + 14, 17, 0); + // matrix 1 + Numerico_Write (DMX_Values[inicial], 1, 1); + Numerico_Write (DMX_Values[inicial + 1], 5, 1); + Numerico_Write (DMX_Values[inicial + 2], 9, 1); + Numerico_Write (DMX_Values[inicial + 3], 13, 1); + Numerico_Write (DMX_Values[inicial + 4], 17, 1); + // matrix 2 + Numerico_Write (DMX_Values[inicial + 5], 1, 2); + Numerico_Write (DMX_Values[inicial + 6], 5, 2); + Numerico_Write (DMX_Values[inicial + 7], 9, 2); + Numerico_Write (DMX_Values[inicial + 8], 13, 2); + Numerico_Write (DMX_Values[inicial + 9], 17, 2); + // matrix 3 + Numerico_Write (DMX_Values[inicial + 10], 1, 3); + Numerico_Write (DMX_Values[inicial + 11], 5, 3); + Numerico_Write (DMX_Values[inicial + 12], 9, 3); + Numerico_Write (DMX_Values[inicial + 13], 13, 3); + Numerico_Write (DMX_Values[inicial + 14], 17, 3); +} + +void GUI_Control_Matrix() +{ + int Inicial = 1; + Canal_Actual = 1; +inicio: + lcd.clear(); + lcd.setCursor (0, 0); + lcd.print("c--- Mb Exi -"); + lcd.setCursor (7, 0); + if (Universo_Actual == 0) + { + lcd.print("-"); + } + else + { + lcd.print(Universo_Actual); + } + Multi_Matrix (Inicial); + // Cursor + LCD_Col_Pos = 12; // posicion de cursor + LCD_Row_Pos = 0; // posicion e cursor + // configuracion de cursor + Cursor_Conf_Clear(); // limpiar array + // Row 0 + Cursor_Conf[0][4] = 1; // Memory + Cursor_Conf[0][8] = 1; // Unit + Cursor_Conf[0][12] = 1; // Banco Inicial + Cursor_Conf[0][16] = 1; // Banco Final + // Row 1 + Cursor_Conf[1][0] = 1; + Cursor_Conf[1][4] = 1; + Cursor_Conf[1][8] = 1; + Cursor_Conf[1][12] = 1; + Cursor_Conf[1][16] = 1; + // Row 2 + Cursor_Conf[2][0] = 1; + Cursor_Conf[2][4] = 1; + Cursor_Conf[2][8] = 1; + Cursor_Conf[2][12] = 1; + Cursor_Conf[2][16] = 1; + // Row 3 + Cursor_Conf[3][0] = 1; + Cursor_Conf[3][4] = 1; + Cursor_Conf[3][8] = 1; + Cursor_Conf[3][12] = 1; + Cursor_Conf[3][16] = 1; + // navegar +Banco: + GUI_Navegar(1, Inicial); + // Acciones + // Memory + if (LCD_Col_Pos == 4 && LCD_Row_Pos == 0) + { + GUI_Memory(); + goto inicio; + } + // Control + if (LCD_Col_Pos == 8 && LCD_Row_Pos == 0) + { + GUI_Control_Options(); + goto inicio; + } + // Banco Inicial + if (LCD_Col_Pos == 12 && LCD_Row_Pos == 0) + { + Num_Row_Pos = 0; + Num_Col_Pos = 13; + Num_Val = Inicial; // para dejar el numero que estaba si no se cambia + Numerico_Calc(0); + if (Num_Val > 498) // limite de matriz + { + Num_Val = 498; + } + if (Num_Val == 0) // limite de matriz + { + Num_Val = 1; + } + Inicial = Num_Val; + goto inicio; + } + // Banco Final + if (LCD_Col_Pos == 16 && LCD_Row_Pos == 0) + { + Num_Row_Pos = 0; + Num_Col_Pos = 17; + if (Inicial == 1) + { + Num_Val = 15; + } + else + { + Num_Val = Inicial - 14; // para dejar el numero que estaba si no se cambia + Numerico_Calc(0); + } + if (Num_Val > 512) // limite de matriz + { + Inicial = 498; + goto inicio; + } + if (Num_Val < 15) // limite de matriz + { + Inicial = 1; + goto inicio; + } + Inicial = Num_Val - 14; + goto inicio; + } + // posicion 1 + if (LCD_Col_Pos == 0 && LCD_Row_Pos == 1) + { + Canal_Actual = Inicial; + goto Salida_DMX; + } + // posicion 2 + if (LCD_Col_Pos == 4 && LCD_Row_Pos == 1) + { + Canal_Actual = Inicial + 1; + goto Salida_DMX; + } + // posicion 3 + if (LCD_Col_Pos == 8 && LCD_Row_Pos == 1) + { + Canal_Actual = Inicial + 2; + goto Salida_DMX; + } + // posicion 4 + if (LCD_Col_Pos == 12 && LCD_Row_Pos == 1) + { + Canal_Actual = Inicial + 3; + goto Salida_DMX; + } + // posicion 5 + if (LCD_Col_Pos == 16 && LCD_Row_Pos == 1) + { + Canal_Actual = Inicial + 4; + goto Salida_DMX; + } + // posicion 6 + if (LCD_Col_Pos == 0 && LCD_Row_Pos == 2) + { + Canal_Actual = Inicial + 5; + goto Salida_DMX; + } + // posicion 7 + if (LCD_Col_Pos == 4 && LCD_Row_Pos == 2) + { + Canal_Actual = Inicial + 6; + goto Salida_DMX; + } + // posicion 8 + if (LCD_Col_Pos == 8 && LCD_Row_Pos == 2) + { + Canal_Actual = Inicial + 7; + goto Salida_DMX; + } + // posicion 9 + if (LCD_Col_Pos == 12 && LCD_Row_Pos == 2) + { + Canal_Actual = Inicial + 8; + goto Salida_DMX; + } + // posicion 10 + if (LCD_Col_Pos == 16 && LCD_Row_Pos == 2) + { + Canal_Actual = Inicial + 9; + goto Salida_DMX; + } + // posicion 11 + if (LCD_Col_Pos == 0 && LCD_Row_Pos == 3) + { + Canal_Actual = Inicial + 10; + goto Salida_DMX; + } + // posicion 12 + if (LCD_Col_Pos == 4 && LCD_Row_Pos == 3) + { + Canal_Actual = Inicial + 11; + goto Salida_DMX; + } + // posicion 13 + if (LCD_Col_Pos == 8 && LCD_Row_Pos == 3) + { + Canal_Actual = Inicial + 12; + goto Salida_DMX; + } + // posicion 14 + if (LCD_Col_Pos == 12 && LCD_Row_Pos == 3) + { + Canal_Actual = Inicial + 13; + goto Salida_DMX; + } + // posicion 15 + if (LCD_Col_Pos == 16 && LCD_Row_Pos == 3) + { + Canal_Actual = Inicial + 14; + goto Salida_DMX; + } +Salida_DMX: + Num_Row_Pos = LCD_Row_Pos; + Num_Col_Pos = LCD_Col_Pos + 1; + Num_Val = DMX_Values[Canal_Actual]; // para dejar el numero que estaba si no se cambia + Numerico_Calc(1); + if (Num_Val == 612) // ubicar + { + Ubicar(); + Num_Col_Pos = Num_Col_Pos - 4; + } + if (Num_Val == 712) // analogo + { + Analog_Read_DMX(Num_Col_Pos - 2, Num_Row_Pos); + Num_Col_Pos = Num_Col_Pos - 4; + goto Banco; + } + if (Num_Val > 255) + { + Num_Val = 255; + Numerico_Write (255, Num_Col_Pos + 2, Num_Row_Pos); + } + ArduinoDmx0.TxBuffer[Canal_Actual - 1] = Num_Val; + DMX_Values[Canal_Actual] = Num_Val; + goto Banco; +} + +void Cursor_Conf_Clear() +{ + for (byte Conteo_Col = 0; Conteo_Col <= 19; Conteo_Col ++) + { + for (byte Conteo_Row = 0; Conteo_Row <= 3; Conteo_Row ++) + { + Cursor_Conf[Conteo_Row][Conteo_Col] = 0; + } + } +} + +void GUI_Navegar(byte matrix, int banco) +{ + int Boton_Delay_Cursor = 300; // delay de lectura de boton + byte LCD_Col_Pos_Ant; // saber el estado anterior para borrar cursor + byte LCD_Row_Pos_Ant; // saber el estado anterior para borrar cursor + // guardar valor anterior de row col + LCD_Col_Pos_Ant = LCD_Col_Pos; + LCD_Row_Pos_Ant = LCD_Row_Pos; + // Dibujar cursor + lcd.setCursor (LCD_Col_Pos, LCD_Row_Pos); + lcd.print(">"); + // navegacion +Dibujar: + byte Dibujar_Cursor = 0; // saber si dibujar cursor para evitar repeticiones en lcd, 0 no dibujar, 1 dibujar >, 2 dibujar + + // LCD Back Light * + digitalWrite(Boton_Array_1, LOW); // lectura linea 1 + if (digitalRead(Boton_Array_D) == LOW) + { + delay(Boton_Delay_Teclado); + Light_En(); + } + digitalWrite(Boton_Array_1, HIGH); // lectura linea 1 + // Left + if (digitalRead(Boton_Left) == LOW) + { + delay (Boton_Delay_Cursor); + byte Salida_Left = 0; + byte LCD_Col_Pos_Temp = 0; + LCD_Col_Pos_Temp = LCD_Col_Pos; + while (Salida_Left == 0) + { + if (LCD_Col_Pos_Temp == 0) + { + LCD_Col_Pos_Temp = 20; + } + LCD_Col_Pos_Temp = LCD_Col_Pos_Temp - 1; + if (Cursor_Conf[LCD_Row_Pos][LCD_Col_Pos_Temp] == 1) + { + LCD_Col_Pos = LCD_Col_Pos_Temp; + Dibujar_Cursor = 1; + Salida_Left = 1; + } + } + goto Salida; + } + // Right + if (digitalRead(Boton_Right) == LOW) + { + delay(Boton_Delay_Cursor); + byte Salida_Right = 0; + byte LCD_Col_Pos_Temp = 0; + LCD_Col_Pos_Temp = LCD_Col_Pos; + while (Salida_Right == 0) + { + LCD_Col_Pos_Temp = LCD_Col_Pos_Temp + 1; + if (LCD_Col_Pos_Temp >= 20) + { + LCD_Col_Pos_Temp = 0; // regresar al cero + } + if (Cursor_Conf[LCD_Row_Pos][LCD_Col_Pos_Temp] == 1) + { + LCD_Col_Pos = LCD_Col_Pos_Temp; + Dibujar_Cursor = 1; + Salida_Right = 1; + } + } + goto Salida; + } + // Down + if (digitalRead(Boton_Down) == LOW) + { + delay(Boton_Delay_Cursor); + byte Salida_Down = 0; + byte LCD_Row_Pos_Temp = 0; + LCD_Row_Pos_Temp = LCD_Row_Pos; + while (Salida_Down == 0) + { + LCD_Row_Pos_Temp = LCD_Row_Pos_Temp + 1; + if (LCD_Row_Pos_Temp >= 4) + { + LCD_Row_Pos_Temp = 0; // regresar al cero + } + if (Cursor_Conf[LCD_Row_Pos_Temp][LCD_Col_Pos] == 1) + { + LCD_Row_Pos = LCD_Row_Pos_Temp; + Dibujar_Cursor = 1; + Salida_Down = 1; + } + } + goto Salida; + } + // Up + if (digitalRead(Boton_Up) == LOW) + { + delay(Boton_Delay_Cursor); + byte Salida_Up = 0; + byte LCD_Row_Pos_Temp; + LCD_Row_Pos_Temp = LCD_Row_Pos; + while (Salida_Up == 0) + { + if (LCD_Row_Pos_Temp <= 0) + { + LCD_Row_Pos_Temp = 4; + } + LCD_Row_Pos_Temp = LCD_Row_Pos_Temp - 1; + if (Cursor_Conf[LCD_Row_Pos_Temp][LCD_Col_Pos] == 1) + { + Dibujar_Cursor = 1; + LCD_Row_Pos = LCD_Row_Pos_Temp; + Salida_Up = 1; + } + } + goto Salida; + } + // Center + if (digitalRead(Boton_Center) == LOW) + { + delay(Boton_Delay_Cursor); + byte Salida_Center = 0; + while (Salida_Center == 0) + { + if (Cursor_Conf[LCD_Row_Pos][LCD_Col_Pos] == 1) + { + Dibujar_Cursor = 2; // dibujar + + Salida_Center = 1; + } + } + } +Salida: + // Dibujar Cursor + if (Dibujar_Cursor > 0) + { + if (Dibujar_Cursor == 1) + { + // borra el anterior + lcd.setCursor (LCD_Col_Pos_Ant, LCD_Row_Pos_Ant); + lcd.print(" "); + // escribir > + lcd.setCursor (LCD_Col_Pos, LCD_Row_Pos); + lcd.print(">"); + // matrix print posicion + if (matrix == 1) + { + // banco inicial + if (LCD_Col_Pos == 12 && LCD_Row_Pos == 0) + { + lcd.setCursor(1, 0); + lcd.print("---"); + goto salida; + } + // banco final + if (LCD_Col_Pos == 16 && LCD_Row_Pos == 0) + { + lcd.setCursor(1, 0); + lcd.print("---"); + goto salir; + } + // Memory + if (LCD_Col_Pos == 4 && LCD_Row_Pos == 0) + { + lcd.setCursor(1, 0); + lcd.print("---"); + goto salida; + } + // Unitary + if (LCD_Col_Pos == 8 && LCD_Row_Pos == 0) + { + lcd.setCursor(1, 0); + lcd.print("---"); + goto salida; + } + // banco 1 + if (LCD_Col_Pos == 0 && LCD_Row_Pos == 1) + { + Numerico_Write (banco, 1, 0); + goto salida; + } + // banco 2 + if (LCD_Col_Pos == 4 && LCD_Row_Pos == 1) + { + Numerico_Write (banco + 1, 1, 0); + goto salida; + } + // banco 3 + if (LCD_Col_Pos == 8 && LCD_Row_Pos == 1) + { + Numerico_Write (banco + 2, 1, 0); + goto salida; + } + // banco 4 + if (LCD_Col_Pos == 12 && LCD_Row_Pos == 1) + { + Numerico_Write (banco + 3, 1, 0); + goto salida; + } + // banco 5 + if (LCD_Col_Pos == 16 && LCD_Row_Pos == 1) + { + Numerico_Write (banco + 4, 1, 0); + goto salida; + } + // banco 6 + if (LCD_Col_Pos == 0 && LCD_Row_Pos == 2) + { + Numerico_Write (banco + 5, 1, 0); + goto salida; + } + // banco 7 + if (LCD_Col_Pos == 4 && LCD_Row_Pos == 2) + { + Numerico_Write (banco + 6, 1, 0); + goto salida; + } + // banco 8 + if (LCD_Col_Pos == 8 && LCD_Row_Pos == 2) + { + Numerico_Write (banco + 7, 1, 0); + goto salida; + } + // banco 9 + if (LCD_Col_Pos == 12 && LCD_Row_Pos == 2) + { + Numerico_Write (banco + 8, 1, 0); + goto salida; + } + // banco 10 + if (LCD_Col_Pos == 16 && LCD_Row_Pos == 2) + { + Numerico_Write (banco + 9, 1, 0); + goto salida; + } + // banco 11 + if (LCD_Col_Pos == 0 && LCD_Row_Pos == 3) + { + Numerico_Write (banco + 10, 1, 0); + goto salida; + } + // banco 12 + if (LCD_Col_Pos == 4 && LCD_Row_Pos == 3) + { + Numerico_Write (banco + 11, 1, 0); + goto salida; + } + // banco 13 + if (LCD_Col_Pos == 8 && LCD_Row_Pos == 3) + { + Numerico_Write (banco + 12, 1, 0); + goto salida; + } + // banco 14 + if (LCD_Col_Pos == 12 && LCD_Row_Pos == 3) + { + Numerico_Write (banco + 13, 1, 0); + goto salida; + } + // banco 15 + if (LCD_Col_Pos == 16 && LCD_Row_Pos == 3) + { + Numerico_Write (banco + 14, 1, 0); + goto salida; + } + // escribir guion de bancos +salida: + lcd.setCursor(16, 0); + lcd.print("-"); +salir: + { + } + } + } + else + { + // escribir + + lcd.setCursor (LCD_Col_Pos, LCD_Row_Pos); + lcd.print("+"); + } + //salida + LCD_Col_Pos_Ant = LCD_Col_Pos; + LCD_Row_Pos_Ant = LCD_Row_Pos; + if (Dibujar_Cursor == 2) + { + goto Salir; + } + else + { + Dibujar_Cursor = 0; + } + } + goto Dibujar; +Salir: {} +} + +void GUI_Memory_Init() +{ +inicio: + int salir = 0; + lcd.clear (); + // Texto + lcd.setCursor (0, 0); + lcd.print("Initial Memory:"); + lcd.setCursor (2, 2); + lcd.print("Empty"); + lcd.setCursor (9, 2); + lcd.print("Load"); + lcd.setCursor (15, 2); + lcd.print("Clear"); + // bank + lcd.setCursor(18, 0); + lcd.print("b"); + if (Universo_Actual == 0) + { + lcd.print("-"); + } + else + { + lcd.print(Universo_Actual); + } + // Cursor + LCD_Col_Pos = 1; // posicion de cursor + LCD_Row_Pos = 2; + // configuracion de cursor + Cursor_Conf_Clear(); // limpiar array + // Acciones + Cursor_Conf[2][1] = 1; // Empty + Cursor_Conf[2][8] = 1; // Load + Cursor_Conf[2][14] = 1; // Clear + // navegar + GUI_Navegar(0, 0); + // Acciones + // Load + if (LCD_Col_Pos == 8 && LCD_Row_Pos == 2) + { + salir = EEPROM_Load(); + if (salir == 1) + { + goto inicio; + } + GUI_Control_Options(); + } + // Clear + if (LCD_Col_Pos == 14 && LCD_Row_Pos == 2) + { + salir = EEPROM_Clear(); + if (salir == 1) + { + goto inicio; + } + GUI_Control_Options(); + } + // Empty + if (LCD_Col_Pos == 1 && LCD_Row_Pos == 2) + { + GUI_Control_Options(); + } +} + +int GUI_Memory_Bank(byte Opcion) +{ + // regresa 1 si se selecciona salir, de lo contrario 0 + // recibe opcion para pintar en la pantalla lo que se selecciono + int salir = 0; + lcd.clear (); + delay (200); // retardo para no seleccionar inmediatamente la opcion del banco + // Texto + lcd.setCursor (6, 0); + lcd.print("Memory Bank:"); + lcd.setCursor (1, 1); + lcd.print("Bank1 Bank4 Bank7"); + lcd.setCursor (1, 2); + lcd.print("Bank2 Bank5 Bank8"); + lcd.setCursor (1, 3); + lcd.print("Bank3 Bank6 Exit"); + switch (Opcion) + { + case 1: + lcd.setCursor (1, 0); + lcd.print("Save"); + break; + case 2: + lcd.setCursor (1, 0); + lcd.print("Load"); + break; + case 3: + lcd.setCursor (0, 0); + lcd.print("Clear"); + break; + } + // Universo Actual + lcd.setCursor (19, 0); + if (Universo_Actual == 0) + { + lcd.print("-"); + } + else + { + lcd.print(Universo_Actual); + } + // Cursor inicial + LCD_Col_Pos = 0; // posicion de cursor + LCD_Row_Pos = 1; + // configuracion de cursor + Cursor_Conf_Clear(); // limpiar array + // Acciones + Cursor_Conf[1][0] = 1; // Bank 1 + Cursor_Conf[2][0] = 1; // Bank 2 + Cursor_Conf[3][0] = 1; // Bank 3 + Cursor_Conf[1][7] = 1; // Bank 4 + Cursor_Conf[2][7] = 1; // Bank 5 + Cursor_Conf[3][7] = 1; // Bank 6 + Cursor_Conf[1][14] = 1; // Bank 7 + Cursor_Conf[2][14] = 1; // Bank 8 + Cursor_Conf[3][14] = 1; // Exit + // navegar + GUI_Navegar(0, 0); + // Acciones + // Bank 1 + if (LCD_Col_Pos == 0 && LCD_Row_Pos == 1) + { + Universo_Actual = 1; + goto Salida; + } + // Bank 2 + if (LCD_Col_Pos == 0 && LCD_Row_Pos == 2) + { + Universo_Actual = 2; + goto Salida; + } + // Bank 3 + if (LCD_Col_Pos == 0 && LCD_Row_Pos == 3) + { + Universo_Actual = 3; + goto Salida; + } + // Bank 4 + if (LCD_Col_Pos == 7 && LCD_Row_Pos == 1) + { + Universo_Actual = 4; + goto Salida; + } + // Bank 5 + if (LCD_Col_Pos == 7 && LCD_Row_Pos == 2) + { + Universo_Actual = 5; + goto Salida; + } + // Bank 6 + if (LCD_Col_Pos == 7 && LCD_Row_Pos == 3) + { + Universo_Actual = 6; + goto Salida; + } + // Bank 7 + if (LCD_Col_Pos == 14 && LCD_Row_Pos == 1) + { + Universo_Actual = 7; + goto Salida; + } + // Bank 8 + if (LCD_Col_Pos == 14 && LCD_Row_Pos == 2) + { + Universo_Actual = 8; + goto Salida; + } + // Exit + if (LCD_Col_Pos == 14 && LCD_Row_Pos == 3) + { + salir = 1; + } +Salida: + return salir; +} + +void GUI_Memory() +{ +iniciar: + lcd.clear (); + // Texto + lcd.setCursor (0, 0); + lcd.print("Memory: b"); + if (Universo_Actual == 0) + { + lcd.print("-"); + } + else + { + lcd.print(Universo_Actual); + } + lcd.setCursor (1, 1); + lcd.print("Save"); + lcd.setCursor (1, 2); + lcd.print("Load"); + lcd.setCursor (1, 3); + lcd.print("Clear"); + lcd.setCursor (7, 2); + lcd.print("ClearAll"); + lcd.setCursor (7, 1); + lcd.print("BlackOut"); + lcd.setCursor (16, 3); + lcd.print("Exit"); + lcd.setCursor (7, 3); + lcd.print("EmptyRAM"); + // Cursor + LCD_Col_Pos = 0; // posicion de cursor + LCD_Row_Pos = 1; + // configuracion de cursor + Cursor_Conf_Clear(); // limpiar array + // Acciones + Cursor_Conf[1][0] = 1; // Save + Cursor_Conf[2][0] = 1; // Load + Cursor_Conf[3][0] = 1; // Clear + Cursor_Conf[2][6] = 1; // Clear All + Cursor_Conf[3][6] = 1; // Empty RAM + Cursor_Conf[1][6] = 1; // Black Out + Cursor_Conf[3][15] = 1; // Exit + // navegar +regresa: + GUI_Navegar(0, 0); + // Acciones + // Load + if (LCD_Col_Pos == 0 && LCD_Row_Pos == 2) + { + if (EEPROM_Load() == 1) + { + goto iniciar; + } + goto salida; + } + // Clear + if (LCD_Col_Pos == 0 && LCD_Row_Pos == 3) + { + if (EEPROM_Clear() == 1) + { + goto iniciar; + } + goto salida; + } + // Clear All + if (LCD_Col_Pos == 6 && LCD_Row_Pos == 2) + { + EEPROM_Clear_All(); + goto salida; + } + // Save + if (LCD_Col_Pos == 0 && LCD_Row_Pos == 1) + { + if (EEPROM_Save() == 1) + { + goto iniciar; + } + goto salida; + } + // Empty RAM + if (LCD_Col_Pos == 6 && LCD_Row_Pos == 3) + { + EEPROM_Empty(); + goto salida; + } + // Black Out + if (LCD_Col_Pos == 6 && LCD_Row_Pos == 1) + { + Black_Out(); + goto regresa; + } + // Exit + if (LCD_Col_Pos == 15 && LCD_Row_Pos == 3) + { + + } +salida: {} +} + +void GUI_Control_Secuencer() +{ + // secuenciador de bancos guardados en eeprom + int Delay_Secuencia = 1; + int First_Bank = 1; + int Final_Bank = 8; + lcd.clear (); + + // Texto + lcd.setCursor (0, 0); + lcd.print("Secuencer Banks: b"); + if (Universo_Actual == 0) + { + lcd.print("-"); + } + else + { + lcd.print(Universo_Actual); + } + lcd.setCursor (4, 1); + lcd.print("Delay 001x100=mS"); + lcd.setCursor (0, 2); + lcd.print("FirstBank 001 Exit"); + lcd.setCursor (0, 3); + lcd.print("FinalBank 008 Start"); + // Cursor + LCD_Col_Pos = 9; // posicion de cursor + LCD_Row_Pos = 1; + // configuracion de cursor + Cursor_Conf_Clear(); // limpiar array + // Acciones + Cursor_Conf[1][9] = 1; // Delay + Cursor_Conf[2][9] = 1; // First Bank + Cursor_Conf[3][9] = 1; // Final Bank + Cursor_Conf[2][14] = 1; // Control + Cursor_Conf[3][14] = 1; // start +inicio: + lcd.setCursor (15, 3); + lcd.print("Start"); + lcd.noBlink(); + + // navegar + GUI_Navegar(0, 0); + + // Acciones + // Delay + if (LCD_Col_Pos == 9 && LCD_Row_Pos == 1) + { + Num_Row_Pos = 1; + Num_Col_Pos = 10; + Num_Val = Delay_Secuencia; // para dejar el numero que estaba si no se cambia + Numerico_Calc(0); + if (Num_Val == 0) + { + Numerico_Write (1, 10, 1); + Delay_Secuencia = 1; + Numerico_Write (Delay_Secuencia, 10, 1); + } + else + { + Delay_Secuencia = Num_Val; // por el multiplicador + } + if (Num_Val > 100) + { + Delay_Secuencia = 100; + Numerico_Write (Delay_Secuencia, 10, 1); + } + goto inicio; + } + // First Bank + if (LCD_Col_Pos == 9 && LCD_Row_Pos == 2) + { + Num_Row_Pos = 2; + Num_Col_Pos = 10; + Num_Val = First_Bank; // para dejar el numero que estaba si no se cambia + Numerico_Calc(0); + First_Bank = Num_Val; + if (Num_Val == 0) + { + First_Bank = 1; + Numerico_Write (First_Bank, 10, 2); + } + if (Num_Val > 8) + { + Numerico_Write (8, 10, 2); + First_Bank = 8; + } + goto inicio; + } + // Final Bank + if (LCD_Col_Pos == 9 && LCD_Row_Pos == 3) + { + Num_Row_Pos = 3; + Num_Col_Pos = 10; + Num_Val = Final_Bank; // para dejar el numero que estaba si no se cambia + Numerico_Calc(0); + Final_Bank = Num_Val; + if (Num_Val == 0) + { + Final_Bank = 1; + Numerico_Write (Final_Bank, 10, 3); + } + if (Num_Val > 8) + { + Numerico_Write (8, 10, 2); + Final_Bank = 8; + } + goto inicio; + } + // Control + if (LCD_Col_Pos == 14 && LCD_Row_Pos == 2) + { + // restablecer salida dmx como estaba antes de entrar + for (int Canal = 0; Canal <= 512; Canal ++) + { + ArduinoDmx0.TxBuffer[Canal] = DMX_Values[Canal]; // salida a DMX + } + GUI_Control_Options (); + } + // start + if (LCD_Col_Pos == 14 && LCD_Row_Pos == 3) + { + // validar + if (First_Bank == Final_Bank) + { + First_Bank = 1; + Numerico_Write (First_Bank, 10, 2); + Final_Bank = 8; + Numerico_Write (Final_Bank, 10, 2); + goto inicio; + } + // LCD + lcd.setCursor (14, 3); + lcd.print("+"); + lcd.setCursor (15, 3); + lcd.print("Stop "); + // establecer reversa o adelante + byte Adelante_Reversa = 0; // 0 Adelante, 1 Reversa + // adelante + if (First_Bank < Final_Bank) + { + Adelante_Reversa = 0; + } + // reversa + if (First_Bank > Final_Bank) + { + Adelante_Reversa = 1; + } + // establecer bancos a secuenciar + byte Bancos [9] = {0, 0, 0, 0, 0, 0, 0, 0}; + if (Adelante_Reversa == 0) + { + for (byte Bank = 1; Bank <= 8; Bank ++) + { + if (Bank >= First_Bank && Bank <= Final_Bank) + { + Bancos[Bank] = 1; + } + } + } + if (Adelante_Reversa == 1) + { + for (byte Bank = 8; Bank >= 1; Bank --) + { + if (Bank <= First_Bank && Bank >= Final_Bank) + { + Bancos[Bank] = 1; + } + } + } + //Secuenciar + byte value = 0; + lcd.blink(); + + // adelante + if (Adelante_Reversa == 0) + { +contar: + for (byte conteo = 1; conteo <= 8; conteo ++) + { + if (Bancos [conteo] == 1) + { + lcd.setCursor (19, 0); + lcd.print(conteo); + lcd.setCursor (19, 3); + for (int canal = 0; canal <= 511; canal ++) + { + switch (conteo) + { + case 1: + value = EEPROM.read(canal); + ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX + break; + case 2: + value = EEPROM.read(canal + 512); + ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX + break; + case 3: + value = EEPROM.read(canal + 1024); + ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX + break; + case 4: + value = EEPROM.read(canal + 1536); + ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX + break; + case 5: + value = EEPROM.read(canal + 2048); + ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX + break; + case 6: + value = EEPROM.read(canal + 2560); + ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX + break; + case 7: + value = EEPROM.read(canal + 3072); + ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX + break; + case 8: + value = EEPROM.read(canal + 3584); + ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX + break; + } + } + //delay + long delay_contar = Delay_Secuencia * 100; + while (digitalRead(Boton_Center) == HIGH) // lectura del boton centro + { + for (long contar = 0; contar <= delay_contar; contar ++) + { + delay(1); + if (digitalRead(Boton_Center) == LOW) + { + goto salida; + } + } + goto Delay_Salir; + } +salida: + delay(500); // rebote de boton + goto inicio; +Delay_Salir: {} + } + } + goto contar; + } + + // reversa + if (Adelante_Reversa == 1) + { +contar_rev: + for (byte conteo = 8; conteo >= 1; conteo --) + { + if (Bancos [conteo] == 1) + { + lcd.setCursor (19, 0); + lcd.print(conteo); + lcd.setCursor (19, 3); + for (int canal = 0; canal <= 511; canal ++) + { + switch (conteo) + { + case 1: + value = EEPROM.read(canal); + ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX + break; + case 2: + value = EEPROM.read(canal + 512); + ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX + break; + case 3: + value = EEPROM.read(canal + 1024); + ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX + break; + case 4: + value = EEPROM.read(canal + 1536); + ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX + break; + case 5: + value = EEPROM.read(canal + 2048); + ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX + break; + case 6: + value = EEPROM.read(canal + 2560); + ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX + break; + case 7: + value = EEPROM.read(canal + 3072); + ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX + break; + case 8: + value = EEPROM.read(canal + 3584); + ArduinoDmx0.TxBuffer[canal] = value; // salida a DMX + break; + } + } + //delay + long delay_contar = Delay_Secuencia * 100; + while (digitalRead(Boton_Center) == HIGH) // lectura del boton centro + { + for (long contar = 0; contar <= delay_contar; contar ++) + { + delay(1); + if (digitalRead(Boton_Center) == LOW) + { + goto salida_rev; + } + } + goto Delay_Salir_Rev; + } +salida_rev: + delay(500); // rebote de boton + goto inicio; +Delay_Salir_Rev: {} + } + } + goto contar_rev; + } + } + goto inicio; +} + +void Black_Out() +{ + lcd.setCursor (15, 1); + lcd.blink(); + // limpiar universo + for (int Canal = 1; Canal <= 512; Canal ++) + { + ArduinoDmx0.TxBuffer[Canal - 1] = 0; + } + // esperar al boton centro para cancelar + while (digitalRead(Boton_Center) == HIGH) + { + } + delay(300); // retardo de rebote de boton + // regresar el universo a su lugar + for (int Canal = 1; Canal <= 512; Canal ++) + { + ArduinoDmx0.TxBuffer[Canal - 1] = DMX_Values[Canal]; + } + lcd.setCursor (6, 2); + lcd.noBlink(); +} + +int EEPROM_Save() +{ + // guarda el universo en la eeprom + // regresa 1 si se selecciona exit + int cancel = 0; // regresa 1 si se selecciona salir + int bank; // regresa 1 si se selecciona salir + int EEPROM_Add = 0; // direccion de eeprom para universos + bank = GUI_Memory_Bank(1); // seleccinar banco + if (bank == 1) + { + cancel = 1; + goto salida; + } + lcd.clear (); + lcd.setCursor (1, 1); + lcd.print ("Memory Saving..."); + lcd.setCursor (1, 2); + lcd.print ("Bank: "); + lcd.setCursor (7, 2); + lcd.print (Universo_Actual); + lcd.setCursor (19, 3); + lcd.blink(); + for (int Canal = 0; Canal <= 511; Canal ++) + { + // Escritura de universo EEPROM + switch (Universo_Actual) + { + case 1: + EEPROM_Add = 0 + Canal; + break; + case 2: + EEPROM_Add = 512 + Canal; + break; + case 3: + EEPROM_Add = 1024 + Canal; + break; + case 4: + EEPROM_Add = 1536 + Canal; + break; + case 5: + EEPROM_Add = 2048 + Canal; + break; + case 6: + EEPROM_Add = 2560 + Canal; + break; + case 7: + EEPROM_Add = 3072 + Canal; + break; + case 8: + EEPROM_Add = 3584 + Canal; + if (EEPROM_Add > EEPROM_Limit) + { + EEPROM_Add = EEPROM_Limit; + } + break; + } + EEPROM.write(EEPROM_Add, DMX_Values[Canal + 1]); // lectura desde EEPROM + } + lcd.clear (); + lcd.setCursor (3, 1); + lcd.print ("Memory Saved!"); + lcd.setCursor (3, 2); + lcd.print ("Bank: "); + lcd.print (Universo_Actual); + lcd.setCursor (19, 3); + delay (1000); + lcd.noBlink(); +salida: + return cancel; +} + +int EEPROM_Load() +{ + // guarda los valores en la eeprom + // regresa 1 si se selecciona exit + int cancel = 0; // regresa 1 si se selecciona salir + int bank; // regresa 1 si se selecciona salir + int EEPROM_Add = 0; // seleccion de universo + bank = GUI_Memory_Bank(2); // seleccinar banco + if (bank == 1) + { + cancel = 1; + goto salida; + } + lcd.clear (); + for (int Canal = 1; Canal <= 512; Canal ++) + { + // Escritura de universo EEPROM + switch (Universo_Actual) + { + case 1: + EEPROM_Add = 0 + Canal - 1; + break; + case 2: + EEPROM_Add = 512 + Canal - 1; + break; + case 3: + EEPROM_Add = 1024 + Canal - 1; + break; + case 4: + EEPROM_Add = 1536 + Canal - 1; + break; + case 5: + EEPROM_Add = 2048 + Canal - 1; + break; + case 6: + EEPROM_Add = 2560 + Canal - 1; + break; + case 7: + EEPROM_Add = 3072 + Canal - 1; + break; + case 8: + EEPROM_Add = 3584 + Canal - 1; + if (EEPROM_Add > EEPROM_Limit) + { + EEPROM_Add = EEPROM_Limit; + } + break; + } + DMX_Values[Canal] = EEPROM.read(EEPROM_Add); // lectura desde EEPROM + ArduinoDmx0.TxBuffer[Canal - 1] = DMX_Values[Canal]; // salida a DMX + } + lcd.clear (); + lcd.setCursor (3, 1); + lcd.print ("Memory Loaded!"); + lcd.setCursor (3, 2); + lcd.print ("Bank: "); + lcd.print (Universo_Actual); + lcd.setCursor (19, 3); + lcd.blink(); + delay (1000); + lcd.noBlink(); +salida: + return cancel; +} + +void EEPROM_Load_Init() +{ + // carga los valores en la eeprom al inicio + int EEPROM_Add = 0; + Universo_Actual = EEPROM.read(Bank_Init_Add); + if (Universo_Actual == 0) + { + goto salir; + } + for (int Canal = 1; Canal <= 512; Canal ++) + { + // Escritura de universo EEPROM + switch (Universo_Actual) + { + case 1: + EEPROM_Add = 0 + Canal - 1; + break; + case 2: + EEPROM_Add = 512 + Canal - 1; + break; + case 3: + EEPROM_Add = 1024 + Canal - 1; + break; + case 4: + EEPROM_Add = 1536 + Canal - 1; + break; + case 5: + EEPROM_Add = 2048 + Canal - 1; + break; + case 6: + EEPROM_Add = 2560 + Canal - 1; + break; + case 7: + EEPROM_Add = 3072 + Canal - 1; + break; + case 8: + EEPROM_Add = 3584 + Canal - 1; + if (EEPROM_Add > EEPROM_Limit) + { + EEPROM_Add = EEPROM_Limit; + } + break; + } + DMX_Values[Canal] = EEPROM.read(EEPROM_Add); // lectura desde EEPROM + ArduinoDmx0.TxBuffer[Canal - 1] = DMX_Values[Canal]; // salida a DMX + } + lcd.clear (); + lcd.setCursor (3, 1); + lcd.print ("Memory Loaded!"); + lcd.setCursor (3, 2); + lcd.print ("Bank: "); + lcd.print (Universo_Actual); + lcd.setCursor (10, 2); + lcd.blink(); + delay (2000); + lcd.noBlink(); +salir: + {} +} + +void EEPROM_Empty() +{ + // solo borra la ram + // no hay retorno al menu anterior + lcd.clear (); + for (int Canal = 1; Canal <= 512; Canal ++) + { + DMX_Values[Canal] = 0; // lectura desde EEPROM + ArduinoDmx0.TxBuffer[Canal - 1] = 0; // salida a DMX + } + lcd.clear (); + lcd.setCursor (3, 1); + lcd.print ("Memory Emptied!"); + lcd.setCursor (3, 2); + lcd.print ("Bank: RAM"); + lcd.setCursor (19, 3); + lcd.blink(); + delay (1000); + lcd.noBlink(); +} + +int EEPROM_Clear() +{ + // Pone en ceros la memoria EEPROM + // regresa 1 si se selecciona exit + int cancel = 0; // regresa 1 si se selecciona salir + int bank; // regresa 1 si se selecciona salir + int EEPROM_Add = 0; // direccion de eeprom para universos + bank = GUI_Memory_Bank(3); // seleccinar banco + if (bank == 1) // si se selecciono salir + { + cancel = 1; + goto salida; + } + lcd.clear (); + lcd.setCursor (1, 1); + lcd.print ("Memory Cleaning..."); + lcd.setCursor (1, 2); + lcd.print ("Bank: "); + lcd.setCursor (7, 2); + lcd.print (Universo_Actual); + lcd.setCursor (19, 3); + lcd.blink(); + for (int Canal = 0; Canal <= 511; Canal ++) + { + DMX_Values[Canal] = 0; // lectura desde EEPROM + ArduinoDmx0.TxBuffer[Canal] = 0; // salida a DMX + // Escritura de universo EEPROM + switch (Universo_Actual) + { + case 1: + EEPROM_Add = 0 + Canal; + break; + case 2: + EEPROM_Add = 512 + Canal; + break; + case 3: + EEPROM_Add = 1024 + Canal; + break; + case 4: + EEPROM_Add = 1536 + Canal; + break; + case 5: + EEPROM_Add = 2048 + Canal; + break; + case 6: + EEPROM_Add = 2560 + Canal; + break; + case 7: + EEPROM_Add = 3072 + Canal; + break; + case 8: + EEPROM_Add = 3584 + Canal; + if (EEPROM_Add > EEPROM_Limit) + { + EEPROM_Add = EEPROM_Limit; + } + break; + } + EEPROM.write (EEPROM_Add, 0); // escritura EEPROM + } + lcd.clear (); + lcd.setCursor (2, 1); + lcd.print ("Memory Cleaned!"); + lcd.setCursor (2, 2); + lcd.print ("Bank: "); + lcd.print (Universo_Actual); + lcd.setCursor (19, 3); + delay (1000); + lcd.noBlink(); +salida: + return cancel; +} + +void EEPROM_Clear_All() +{ + // Pone en ceros la memoria EEPROM toda + lcd.clear (); + lcd.setCursor (1, 1); + lcd.print ("All"); + lcd.setCursor (1, 2); + lcd.print ("Memory Cleaning..."); + lcd.setCursor (19, 2); + lcd.blink(); + for (int Canal = 0; Canal <= EEPROM_Limit; Canal ++) + { + EEPROM.write (Canal, 0); // escritura EEPROM + if (Canal <= 511) + { + DMX_Values[Canal + 1] = 0; + ArduinoDmx0.TxBuffer[Canal] = 0; // salida a DMX + } + } + lcd.clear (); + lcd.noBlink(); + lcd.setCursor (2, 2); + lcd.print ("Memory Cleaned!"); + lcd.setCursor (2, 1); + lcd.print ("All"); + Universo_Actual = 0; + delay (1000); +} + +void GUI_Control_Options() +{ +inicio: + // LCD + lcd.clear (); + lcd.setCursor (18, 0); + lcd.print ("b"); + if (Universo_Actual == 0) + { + lcd.print ("-"); + } + else + { + lcd.print (Universo_Actual); + } + lcd.setCursor (2, 0); + lcd.print ("Convert"); + lcd.setCursor (2, 1); + lcd.print ("Unitary"); + lcd.setCursor (2, 2); + lcd.print ("Matrix"); + lcd.setCursor (2, 3); + lcd.print ("Chaser"); + lcd.setCursor (11, 3); + lcd.print ("Multiply"); + lcd.setCursor (11, 0); + lcd.print ("Config"); + lcd.setCursor (11, 2); + lcd.print ("Secuencer"); + lcd.setCursor (11, 1); + lcd.print ("Memory"); + // Cursor + LCD_Col_Pos = 1; // posicion de cursor + LCD_Row_Pos = 2; + // configuracion de cursor + Cursor_Conf_Clear(); // limpiar array + // Acciones + Cursor_Conf[1][1] = 1; // Unitary + Cursor_Conf[2][1] = 1; // Matrix + Cursor_Conf[3][1] = 1; // Chaser + Cursor_Conf[3][10] = 1; // Multiply + Cursor_Conf[0][10] = 1; // Config + Cursor_Conf[2][10] = 1; // Secuencer + Cursor_Conf[1][10] = 1; // Memory + Cursor_Conf[0][1] = 1; // Convert + // navegar + GUI_Navegar(0, 0); + // Acciones + // Unitary + if (LCD_Col_Pos == 1 && LCD_Row_Pos == 1) + { + GUI_Control_Unit(); + } + // Matrix + if (LCD_Col_Pos == 1 && LCD_Row_Pos == 2) + { + GUI_Control_Matrix(); + } + // Chaser + if (LCD_Col_Pos == 1 && LCD_Row_Pos == 3) + { + GUI_Control_Chaser(); + } + // Multiply + if (LCD_Col_Pos == 10 && LCD_Row_Pos == 3) + { + GUI_Control_Multiply(); + } + // Config + if (LCD_Col_Pos == 10 && LCD_Row_Pos == 0) + { + GUI_Config(); + } + // Secuencer + if (LCD_Col_Pos == 10 && LCD_Row_Pos == 2) + { + GUI_Control_Secuencer(); + } + // Converter + if (LCD_Col_Pos == 1 && LCD_Row_Pos == 0) + { + GUI_Convert(); + } + // Memory + if (LCD_Col_Pos == 10 && LCD_Row_Pos == 1) + { + GUI_Memory(); + goto inicio; + } +} + +void GUI_Convert() +{ + int valor = 0; // aqui el valor a calcular + int valor_temp = 0; // aqui el valor temporal para las cuentas + int valor_resto = 0; // aqui el valor del resto de la divicion + int valor_Bin [10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // aqui el valor descompuesto en binario + lcd.clear (); + lcd.setCursor (0, 0); + lcd.print ("Bin: OOOOOOOOO I=On"); + lcd.setCursor (5, 1); + lcd.print ("124813612 O=Off"); + lcd.setCursor (9, 2); + lcd.print ("62425"); + lcd.setCursor (0, 3); + lcd.print ("Dec: 000 86 Exit"); + // Cursor + LCD_Col_Pos = 4; // posicion de cursor + LCD_Row_Pos = 3; // posicion e cursor + // configuracion de cursor + Cursor_Conf_Clear(); // limpiar array + // Cursores + Cursor_Conf[0][4] = 1; // Bin + Cursor_Conf[3][4] = 1; // Dec + Cursor_Conf[3][15] = 1; // Exit + //Navegacion: +calc: + GUI_Navegar(0, 0); + // Acciones + // Exit + if (LCD_Col_Pos == 15 && LCD_Row_Pos == 3) + { + GUI_Control_Options(); + } + // Binario a decimal + if (LCD_Col_Pos == 4 && LCD_Row_Pos == 0) + { + // boton de centro para salir + // boton de lados para navegar + // boton arriba abajo para cambiar valor + byte cursor = 5; // posicion de cursor + int boton_retardo = 250; // retardo de boton para estabilidad + byte calcular = 0; // calcular binario a decimal + byte calcular_val = 0; // valor a meter a la matriz para calcular + lcd.blink(); + lcd.setCursor (5, 0); + while (digitalRead(Boton_Center) == HIGH) // salida + { + if (digitalRead(Boton_Right) == LOW) + { + delay(boton_retardo); // esperar a estabilidad + cursor = cursor + 1; + if (cursor > 13) + { + cursor = 5; // regresar al principio + } + lcd.setCursor (cursor, 0); + } + if (digitalRead(Boton_Left) == LOW) + { + delay(boton_retardo); // esperar a estabilidad + cursor = cursor - 1; + if (cursor < 5) + { + cursor = 13; // regresar al final + } + lcd.setCursor (cursor, 0); + } + if (digitalRead(Boton_Up) == LOW) + { + delay(boton_retardo); // esperar a estabilidad + lcd.print ("I"); + lcd.setCursor (cursor, 0); + calcular_val = 1; + calcular = 1; + } + if (digitalRead(Boton_Down) == LOW) + { + delay(boton_retardo); // esperar a estabilidad + lcd.print ("O"); + lcd.setCursor (cursor, 0); + calcular_val = 0; + calcular = 1; + } + if (calcular == 1) + { + calcular = 0; + // agregar a la matriz el valor nuevo + switch (cursor) + { + case 5: // 1 + valor_Bin [1] = calcular_val; + break; + case 6: // 2 + valor_Bin [2] = calcular_val; + break; + case 7: // 4 + valor_Bin [3] = calcular_val; + break; + case 8: // 8 + valor_Bin [4] = calcular_val; + break; + case 9: // 16 + valor_Bin [5] = calcular_val; + break; + case 10: // 32 + valor_Bin [6] = calcular_val; + break; + case 11: // 64 + valor_Bin [7] = calcular_val; + break; + case 12: // 128 + valor_Bin [8] = calcular_val; + break; + case 13: // 256 + valor_Bin [9] = calcular_val; + break; + } + // calcular valor de binario a decimal + valor = 0; + if (valor_Bin [1] == 1) + { + valor = valor + 1; + } + if (valor_Bin [2] == 1) + { + valor = valor + 2; + } + if (valor_Bin [3] == 1) + { + valor = valor + 4; + } + if (valor_Bin [4] == 1) + { + valor = valor + 8; + } + if (valor_Bin [5] == 1) + { + valor = valor + 16; + } + if (valor_Bin [6] == 1) + { + valor = valor + 32; + } + if (valor_Bin [7] == 1) + { + valor = valor + 64; + } + if (valor_Bin [8] == 1) + { + valor = valor + 128; + } + if (valor_Bin [9] == 1) + { + valor = valor + 256; + } + // escribir el valor en decimal + Numerico_Write (valor, 5, 3); + lcd.setCursor (cursor, 0); + } + } + delay(200); // esperar a estabilidad + lcd.noBlink(); + goto calc; + } + // Decimal a binario + if (LCD_Col_Pos == 4 && LCD_Row_Pos == 3) + { + Num_Row_Pos = 3; + Num_Col_Pos = 5; + Numerico_Calc (0); + if (Num_Val > 511) + { + Num_Val = 511; // corregir valor en pantalla + lcd.setCursor (5, 3); + lcd.print ("511"); + } + valor = Num_Val; + // escribir 00000000 en el valor binario para borrar el anterior + lcd.setCursor (5, 0); + lcd.print ("OOOOOOOOO"); + lcd.setCursor (5, 0); + // calcular binario + valor_temp = valor; + for (byte pos = 9; pos >= 1; pos --) + { + valor_resto = valor_temp % 2; + valor_temp = valor_temp / 2; + valor_Bin [pos] = valor_resto; + if (valor_resto == 0) + { + lcd.print ("O"); + } + else + { + lcd.print ("I"); + } + } + goto calc; + } +} + +void GUI_Config() +{ +Inicio: + byte Back_Light_Value = EEPROM.read(BackLight_Add); + byte Contrast_Value = EEPROM.read(Contrast_Add); + byte Bank_Init_Value = EEPROM.read(Bank_Init_Add); + byte Key_Light_Value = EEPROM.read(Key_Light_Add); + // GUI + lcd.clear (); + lcd.setCursor (0, 0); + lcd.print (" KeyLight:"); + Numerico_Write(Key_Light_Value, 11, 0); + lcd.setCursor (15, 2); + lcd.print ("About"); + lcd.setCursor (0, 1); + lcd.print ("BackLight:"); + Numerico_Write(Back_Light_Value, 11, 1); + lcd.setCursor (1, 2); + lcd.print ("Contrast:"); + Numerico_Write(Contrast_Value, 11, 2); + lcd.setCursor (15, 3); + lcd.print ("Exit"); + // Bank + lcd.setCursor (1, 3); + lcd.print ("BankInit:"); + if (Bank_Init_Value > 8 || Bank_Init_Value < 1) + { + lcd.setCursor (11, 3); + lcd.print ("---"); + } + else + { + Numerico_Write(Bank_Init_Value, 11, 3); + } + // Cursor + LCD_Col_Pos = 10; // posicion de cursor + LCD_Row_Pos = 1; // posicion de cursor + // configuracion de cursor + Cursor_Conf_Clear(); // limpiar array + // Cursores + Cursor_Conf[1][10] = 1; // Back Light Value + Cursor_Conf[2][10] = 1; // Contrast Value + Cursor_Conf[3][10] = 1; // Bank init Value + Cursor_Conf[0][10] = 1; // Key Light Value + Cursor_Conf[3][14] = 1; // Exit + Cursor_Conf[2][14] = 1; // About +Navegacion: + GUI_Navegar(0, 0); + // Acciones + //Back Light Value + if (LCD_Col_Pos == 10 && LCD_Row_Pos == 1) + { + Num_Row_Pos = 1; + Num_Col_Pos = 11; + Numerico_Calc (1); + if (Num_Val == 712) + { + lcd.setCursor (10, 1); + lcd.print("a"); // indicar que es analogo + digitalWrite(Boton_Array_3, LOW); // lectura linea 3 + lcd.blink(); + while (digitalRead(Boton_Array_D) == HIGH && digitalRead(Boton_Center) == HIGH) // enter y center para paro + { + Num_Val = analogRead(Pot); // lectura desde el potenciometro + Num_Val = Num_Val / 4; // / 4 porque es de 12 bits + Numerico_Write(Num_Val, 11, 1); + analogWrite(Back_Light_PWM, Num_Val); + delay(50); // retardo de lectura + } + lcd.noBlink(); + digitalWrite(Boton_Array_3, HIGH); // lectura linea 3 + delay(300); // retraso para center + goto salida; + } + if (Num_Val > 255) + { + Num_Val = 255; + Numerico_Write (255, 11, 1); + } + analogWrite(Back_Light_PWM, Num_Val); +salida: + // mecanismo para on off Enable + if (Num_Val == 0) + { + Light_On_Off = 0; + } + if (Num_Val > 0) + { + Light_On_Off = 1; + } + EEPROM.write(BackLight_Add, Num_Val); // guardar valor nuevo + goto Navegacion; + } + //Key Light Value + if (LCD_Col_Pos == 10 && LCD_Row_Pos == 0) + { + Num_Row_Pos = 0; + Num_Col_Pos = 11; + Numerico_Calc (1); + if (Num_Val == 712) + { + lcd.setCursor (10, 0); + lcd.print("a"); // indicar que es analogo + digitalWrite(Boton_Array_3, LOW); // lectura linea 3 + lcd.blink(); + while (digitalRead(Boton_Array_D) == HIGH && digitalRead(Boton_Center) == HIGH) // enter y center para paro + { + Num_Val = analogRead(Pot); // lectura desde el potenciometro + Num_Val = Num_Val / 4; // / 4 porque es de 12 bits + Numerico_Write(Num_Val, 11, 0); + analogWrite(Key_Light_PWM, Num_Val); + delay(50); // retardo de lectura + } + lcd.noBlink(); + digitalWrite(Boton_Array_3, HIGH); // lectura linea 3 + delay(300); // retraso para center + goto salida_key; + } + if (Num_Val > 255) + { + Num_Val = 255; + Numerico_Write (255, 11, 0); + } + analogWrite(Key_Light_PWM, Num_Val); +salida_key: + // mecanismo para on off Enable + if (Num_Val == 0) + { + Light_On_Off = 0; + } + if (Num_Val > 0) + { + Light_On_Off = 1; + } + EEPROM.write(Key_Light_Add, Num_Val); // guardar valor nuevo + goto Navegacion; + } + //Contrast Value + if (LCD_Col_Pos == 10 && LCD_Row_Pos == 2) + { + Num_Row_Pos = 2; + Num_Col_Pos = 11; + Numerico_Calc (1); + if (Num_Val == 712) + { + lcd.setCursor (10, 2); + lcd.print("a"); // indicar que es analogo + digitalWrite(Boton_Array_3, LOW); // lectura linea 3 + lcd.blink(); + while (digitalRead(Boton_Array_D) == HIGH && digitalRead(Boton_Center) == HIGH) // enter y center para paro + { + Num_Val = analogRead(Pot); // lectura desde el potenciometro + Num_Val = Num_Val / 4; // / 4 porque es de 12 bits + if (Num_Val > 149) // limite menor de contraste LCD + { + Numerico_Write(Num_Val, 11, 2); + analogWrite(Contrast_PWM, Num_Val); + } + if (Num_Val < 149) + { + Numerico_Write(150, 11, 2); + } + delay(50); // retardo de lectura + } + lcd.noBlink(); + digitalWrite(Boton_Array_3, HIGH); // lectura linea 3 + delay(300); // retraso para center + goto salir; + } + if (Num_Val > 255) + { + Num_Val = 255; + Numerico_Write (255, 11, 2); + } + if (Num_Val < 150) + { + Num_Val = 150; // limite menor de contraste LCD + Numerico_Write (150, 11, 2); + } + analogWrite(Contrast_PWM, Num_Val); +salir: + EEPROM.write(Contrast_Add, Num_Val); // guardar valor nuevo + goto Navegacion; + } + //Bank init Value + if (LCD_Col_Pos == 10 && LCD_Row_Pos == 3) + { + Num_Row_Pos = 3; + Num_Col_Pos = 11; + Numerico_Calc (1); + if (Num_Val > 8) + { + Num_Val = 8; + Numerico_Write (8, 11, 3); + } + if (Num_Val == 0) + { + lcd.setCursor (11, 3); + lcd.print("---"); + } + EEPROM.write(Bank_Init_Add, Num_Val); // guardar valor nuevo + goto Navegacion; + } + // Exit + if (LCD_Col_Pos == 14 && LCD_Row_Pos == 3) + { + GUI_Control_Options(); + goto Navegacion; + } + // About + if (LCD_Col_Pos == 14 && LCD_Row_Pos == 2) + { + GUI_About(); + GUI_Licence(); + goto Inicio; + } + goto Navegacion; +} + +void GUI_Control_Multiply() +{ + int First_Channel = 1; + long Multiply = 0; + long Quantity = 0; + int Value = 255; +iniciar: + // LCD + lcd.clear (); + lcd.setCursor (0, 0); + lcd.print ("b Value"); + lcd.setCursor (1, 0); + if (Universo_Actual == 0) + { + lcd.print("-"); + } + else + { + lcd.print(Universo_Actual); + } + lcd.setCursor (0, 1); + lcd.print ("First CH Exit"); + lcd.setCursor (0, 2); + lcd.print ("Multiply Memory"); + lcd.setCursor (0, 3); + lcd.print ("Quantity Apply"); + Numerico_Write (Value, 9, 0); + Numerico_Write (First_Channel, 9, 1); + Numerico_Write (Multiply, 9, 2); + Numerico_Write (Quantity, 9, 3); + // Cursor + LCD_Col_Pos = 8; // posicion de cursor + LCD_Row_Pos = 0; +Siguiente: + // configuracion de cursor + Cursor_Conf_Clear(); // limpiar array + // Acciones + Cursor_Conf[1][8] = 1; // first Channel + Cursor_Conf[3][8] = 1; // quantity + Cursor_Conf[2][8] = 1; // Multiply + Cursor_Conf[1][13] = 1; // control + Cursor_Conf[2][13] = 1; // Memory + Cursor_Conf[3][13] = 1; // apply + Cursor_Conf[0][8] = 1; // value + // navegar + GUI_Navegar(0, 0); + // Acciones + // Exit + if (LCD_Col_Pos == 13 && LCD_Row_Pos == 1) + { + GUI_Control_Options(); + } + // Memory + if (LCD_Col_Pos == 13 && LCD_Row_Pos == 2) + { + GUI_Memory(); + goto iniciar; + } + // Apply + if (LCD_Col_Pos == 13 && LCD_Row_Pos == 3) + { + // Validar datos + long valid = Multiply * Quantity; + if (valid > 512) // si no es valido + { + lcd.setCursor(13, 0); + lcd.print("Error! "); + goto Siguiente; + } + // calcular + lcd.setCursor(13, 0); + lcd.print(" "); + lcd.setCursor(14, 3); + lcd.print("Calc.."); + long canal; + for (long conteo = 1; conteo <= Quantity; conteo++) + { + if (conteo == 1) + { + canal = First_Channel; + } + if (conteo != 1) + { + canal = canal + Multiply; + } + if (canal > 512) + { + canal = canal - Multiply; + conteo = Quantity; + } + lcd.setCursor(17, 0); + lcd.print(canal); + delay (5); + ArduinoDmx0.TxBuffer[canal - 1] = Value; + DMX_Values[canal] = Value; + } + lcd.setCursor(13, 0); + lcd.print("Ok!"); + lcd.setCursor(14, 3); + lcd.print("Apply "); + goto Siguiente; + } + // First Channel + if (LCD_Col_Pos == 8 && LCD_Row_Pos == 1) + { + Num_Row_Pos = 1; + Num_Col_Pos = 9; + Num_Val = First_Channel; // para dejar el numero que estaba si no se cambia + Numerico_Calc(0); + First_Channel = Num_Val; + if (First_Channel == 0) + { + First_Channel = 1; + Numerico_Write (First_Channel, 9, 1); + } + if (First_Channel > 512) + { + First_Channel = 512; + Numerico_Write (First_Channel, 9, 1); + } + } + // Multiply + if (LCD_Col_Pos == 8 && LCD_Row_Pos == 2) + { + Num_Row_Pos = 2; + Num_Col_Pos = 9; + Num_Val = Multiply; // para dejar el numero que estaba si no se cambia + Numerico_Calc(0); + Multiply = Num_Val; + if (Multiply == 0) + { + Multiply = 1; + Numerico_Write (Multiply, 9, 2); + } + if (Multiply > 512) + { + Multiply = 512; + Numerico_Write (Multiply, 9, 2); + } + } + // Quantity + if (LCD_Col_Pos == 8 && LCD_Row_Pos == 3) + { + Num_Row_Pos = 3; + Num_Col_Pos = 9; + Num_Val = Quantity; // para dejar el numero que estaba si no se cambia + Numerico_Calc(0); + Quantity = Num_Val; + if (Quantity == 0) + { + Quantity = 1; + Numerico_Write (Quantity, 9, 3); + } + if (Quantity > 512) + { + Quantity = 512; + Numerico_Write (Quantity, 9, 3); + } + } + // Value + if (LCD_Col_Pos == 8 && LCD_Row_Pos == 0) + { + Num_Row_Pos = 0; + Num_Col_Pos = 9; + Num_Val = Value; // para dejar el numero que estaba si no se cambia + Numerico_Calc(1); + Value = Num_Val; + if (Value > 255) + { + Value = 255; + Numerico_Write (Value, 9, 0); + } + } + goto Siguiente; +} + +void GUI_Control_Chaser() +{ + long Delay = 1; + long First = 1; + long Final = 0; + // LCD + lcd.clear (); + lcd.setCursor (0, 0); + lcd.print ("ChaserCH ---"); + lcd.setCursor (3, 1); + lcd.print ("Delay x10=mS"); + lcd.setCursor (0, 2); + lcd.print ("First CH Exit"); + lcd.setCursor (0, 3); + lcd.print ("Final CH Start"); + Numerico_Write (Delay, 9, 1); + Numerico_Write (First, 9, 2); + Numerico_Write (Final, 9, 3); + // Cursor + LCD_Col_Pos = 8; // posicion de cursor + LCD_Row_Pos = 1; +Siguiente: + // configuracion de cursor + Cursor_Conf_Clear(); // limpiar array + // Acciones + Cursor_Conf[1][8] = 1; // Delay + Cursor_Conf[2][8] = 1; // First + Cursor_Conf[3][8] = 1; // Final + Cursor_Conf[2][14] = 1; // control + Cursor_Conf[3][14] = 1; // Start + // navegar + GUI_Navegar(0, 0); + // Acciones + // Control + if (LCD_Col_Pos == 14 && LCD_Row_Pos == 2) + { + // regresar el universo a su lugar + for (int Canal = 1; Canal <= 512; Canal ++) + { + ArduinoDmx0.TxBuffer[Canal - 1] = DMX_Values[Canal]; + } + GUI_Control_Options(); + } + // Start + if (LCD_Col_Pos == 14 && LCD_Row_Pos == 3) + { + long ciclo_longitud = 1300; // numero multiplicador aprox para 1 seg + long ciclo = 0; + long Delay_Cont = 0; + int canal = First; + lcd.setCursor(15, 3); + lcd.print("Stop "); + lcd.blink(); + // borrar canales previos + for (int Canales = 0; Canales <= 512; Canales ++) + { + ArduinoDmx0.TxBuffer[Canales] = 0; // salida a DMX + } + while (digitalRead(Boton_Center) == HIGH) // lectura del boton centro + { + ciclo = ciclo + 1; + if (ciclo == ciclo_longitud) + { + Delay_Cont = Delay_Cont + 1; + if (Delay_Cont == Delay) + { + if (canal > Final) + { + canal = First; + } + Numerico_Write (canal, 9, 0); + lcd.setCursor(19, 3); + // apagar lo anterior + for (long contar = First; contar <= Final; contar ++) + { + ArduinoDmx0.TxBuffer[contar - 1] = 0; + } + // encender el siguiente + ArduinoDmx0.TxBuffer[canal - 1] = 255; + Delay_Cont = 0; + canal = canal + 1; + } + ciclo = 0; + } + } + lcd.noBlink(); + lcd.setCursor(15, 3); + lcd.print("Start"); + delay (300); // evita que le gane la descarga del capacitor + goto Siguiente; + } + // Delay + if (LCD_Col_Pos == 8 && LCD_Row_Pos == 1) + { + Num_Row_Pos = 1; + Num_Col_Pos = 9; + Num_Val = Delay; // para dejar el numero que estaba si no se cambia + Numerico_Calc(0); + Delay = Num_Val; + } + // First + if (LCD_Col_Pos == 8 && LCD_Row_Pos == 2) + { + Num_Row_Pos = 2; + Num_Col_Pos = 9; + Num_Val = First; // para dejar el numero que estaba si no se cambia + Numerico_Calc(0); + First = Num_Val; + if (First == 0) + { + First = 1; + Numerico_Write (First, 9, 2); + } + if (First > 512) + { + First = 512; + Numerico_Write (First, 9, 2); + } + } + // Final + if (LCD_Col_Pos == 8 && LCD_Row_Pos == 3) + { + Num_Row_Pos = 3; + Num_Col_Pos = 9; + Num_Val = Final; // para dejar el numero que estaba si no se cambia + Numerico_Calc(0); + Final = Num_Val; + if (Final == 0) + { + Final = 1; + Numerico_Write (Final, 9, 3); + } + if (Final > 512) + { + Final = 512; + Numerico_Write (Final, 9, 3); + } + } + goto Siguiente; +} + +void Numerico_Write (int valor, int col, int row) +{ + // posicionar el valor en los campos 000 + lcd.setCursor (col, row); + lcd.print ("000"); + if (valor < 10) + { + lcd.setCursor (col + 2, row); + } + if (valor > 9 && valor < 100) + { + lcd.setCursor (col + 1, row); + } + if (valor > 99) + { + lcd.setCursor (col, row); + } + lcd.print (valor); +} + +void GUI_Control_Unit() +{ +Inicio: + Canal_Actual = 1; + // GUI + lcd.clear (); + lcd.setCursor (0, 0); + lcd.print ("Unitary Control: b"); + if (Universo_Actual == 0) + { + lcd.print("-"); + } + else + { + lcd.print(Universo_Actual); + } + lcd.setCursor (14, 2); + lcd.print ("Exit"); + lcd.setCursor (14, 3); + lcd.print ("Memory"); + lcd.setCursor (0, 2); + lcd.print ("Channel: 001"); + lcd.setCursor (2, 3); + lcd.print ("Value:"); + Numerico_Write(DMX_Values[1], 9, 3); + lcd.setCursor (0, 1); + lcd.print ("c002=v"); + Numerico_Write(DMX_Values[2], 6, 1); + lcd.setCursor (11, 1); + lcd.print ("c003=v"); + Numerico_Write(DMX_Values[3], 17, 1); + // Cursor + LCD_Col_Pos = 8; // posicion de cursor + LCD_Row_Pos = 2; // posicion e cursor + // configuracion de cursor + Cursor_Conf_Clear(); // limpiar array + // Cursores + Cursor_Conf[2][8] = 1; // Channel + Cursor_Conf[3][8] = 1; // Value + Cursor_Conf[2][13] = 1; // Control + Cursor_Conf[3][13] = 1; // Memory + // navegar +Navegacion: + GUI_Navegar(0, 0); + // Acciones + //Channel + if (LCD_Col_Pos == 8 && LCD_Row_Pos == 2) + { + Numerico_Write(Canal_Actual, 9, 2); + Num_Row_Pos = 2; + Num_Col_Pos = 9; + Num_Val = Canal_Actual; // para dejar el numero que estaba si no se cambia + Numerico_Calc (0); + if (Num_Val > 512) + { + Num_Val = 512; + Numerico_Write (512, 9, 2); + } + if (Num_Val < 1) + { + Num_Val = 1; + Numerico_Write (1, 9, 2); + } + // mostrar valor actual del canal + Canal_Actual = Num_Val; + Numerico_Write(DMX_Values[Canal_Actual], 9, 3); + // mostrar anterior y siguiente + if (Canal_Actual == 1) + { + Numerico_Write(2, 1, 1); + Numerico_Write(DMX_Values[2], 6, 1); + Numerico_Write(3, 12, 1); + Numerico_Write(DMX_Values[3], 17, 1); + } + if (Canal_Actual == 512) + { + Numerico_Write(510, 1, 1); + Numerico_Write(DMX_Values[510], 6, 1); + Numerico_Write(511, 12, 1); + Numerico_Write(DMX_Values[511], 17, 1); + } + if (Canal_Actual > 1 && Canal_Actual < 512) + { + Numerico_Write(Canal_Actual - 1, 1, 1); + Numerico_Write(DMX_Values[Canal_Actual - 1], 6, 1); + Numerico_Write(Canal_Actual + 1, 12, 1); + Numerico_Write(DMX_Values[Canal_Actual + 1], 17, 1); + } + } + // Value + if (LCD_Col_Pos == 8 && LCD_Row_Pos == 3) + { + Num_Row_Pos = 3; + Num_Col_Pos = 9; + Num_Val = DMX_Values[Canal_Actual]; // para dejar el numero que estaba si no se cambia + Numerico_Calc (1); + if (Num_Val == 612) // ubicar + { + Ubicar(); + } + if (Num_Val == 712) // analogo + { + Analog_Read_DMX(9, 3); + goto Navegacion; + } + if (Num_Val > 255) + { + Num_Val = 255; + Numerico_Write (255, 9, 3); + } + // Escribr valor en dmx + ArduinoDmx0.TxBuffer[Canal_Actual - 1] = Num_Val; + DMX_Values[Canal_Actual] = Num_Val; + goto Navegacion; + } + // Memory + if (LCD_Col_Pos == 13 && LCD_Row_Pos == 3) + { + GUI_Memory(); + goto Inicio; + } + // Control + if (LCD_Col_Pos == 13 && LCD_Row_Pos == 2) + { + GUI_Control_Options(); + } + goto Navegacion; +} + +void Ubicar() +{ + digitalWrite(Boton_Array_4, LOW); + while (digitalRead(Boton_Array_C) == HIGH && digitalRead(Boton_Center) == HIGH) + { + ArduinoDmx0.TxBuffer[Canal_Actual - 1] = 255; + Numerico_Write (255, Num_Col_Pos - 2, Num_Row_Pos); + delay (100); + ArduinoDmx0.TxBuffer[Canal_Actual - 1] = 0; + lcd.setCursor (Num_Col_Pos - 2, Num_Row_Pos); + lcd.print (" "); + delay (100); + } + digitalWrite(Boton_Array_4, HIGH); + delay(300); // rebote de boton enter + lcd.setCursor (Num_Col_Pos, Num_Row_Pos); +} + +void Numerico_Calc(byte value) +{ + // escritura del numero desde el teclado numerico si value es 1 entra opcion de A 255 y B 0 + int Num_Val_Temp_1 = 0; + int Num_Val_Temp_2 = 0; + lcd.setCursor (Num_Col_Pos, Num_Row_Pos); + lcd.print("___"); + lcd.blink(); // mostrar cursor + //Num_Val = 0; + Num_Col_Pos = Num_Col_Pos + 2; + lcd.setCursor (Num_Col_Pos, Num_Row_Pos); + // primer numero + Numerico_Read(); // leer boton + if (Boton_Calc <= 9) + { + lcd.print (Boton_Calc); // escribir valor calculado + lcd.setCursor (Num_Col_Pos, Num_Row_Pos); + Num_Val = Boton_Calc; // valor calculado + Num_Val_Temp_1 = Boton_Calc; // valor temporal para el acarreo + } + if (Boton_Calc == 14) // enter + { + goto Salida; // num val = 0 + } + if (value == 1) // si es un valor + { + if (Boton_Calc == 10) // 255 + { + Num_Val = 255; + goto Salida; + } + if (Boton_Calc == 11) // 000 + { + Num_Val = 0; + goto Salida; + } + if (Boton_Calc == 12) // ubicar + { + Num_Val = 612; + goto Salida_Option; + } + if (Boton_Calc == 13) // analogo + { + Num_Val = 712; + goto Salida_Option; + } + } + // segundo numero + Numerico_Read(); // leer boton + if (Boton_Calc == 14) // enter + { + Num_Val = Num_Val_Temp_1; + goto Salida; // num val = num val anterior + } + if (value == 1) // si es un valor + { + if (Boton_Calc == 10) // 255 + { + Num_Val = 255; + goto Salida; + } + if (Boton_Calc == 11) // 000 + { + Num_Val = 0; + goto Salida; + } + if (Boton_Calc == 12) // ubicar + { + Num_Val = 612; + goto Salida_Option; + } + if (Boton_Calc == 13) // analogo + { + Num_Val = 712; + goto Salida_Option; + } + } + if (Boton_Calc <= 9) + { + // recorrer numero ya impreso + Num_Col_Pos = Num_Col_Pos - 1; + lcd.setCursor (Num_Col_Pos, Num_Row_Pos); + lcd.print (Num_Val_Temp_1); + // dibujar numero nuevo + lcd.print (Boton_Calc); + Num_Val_Temp_2 = Boton_Calc; + Num_Col_Pos = Num_Col_Pos + 1; + lcd.setCursor (Num_Col_Pos, Num_Row_Pos); + } + // Tercer numero + Numerico_Read(); // leer boton + if (Boton_Calc == 14) // enter + { + Num_Val = (Num_Val_Temp_1 * 10) + Num_Val_Temp_2; + goto Salida; + } + if (value == 1) // si es un valor + { + if (Boton_Calc == 10) // 255 + { + Num_Val = 255; + goto Salida; + } + if (Boton_Calc == 11) // 000 + { + Num_Val = 0; + goto Salida; + } + if (Boton_Calc == 12) // ubicar + { + Num_Val = 612; + goto Salida_Option; + } + if (Boton_Calc == 13) // analogo + { + Num_Val = 712; + goto Salida_Option; + } + } + if (Boton_Calc <= 9) + { + // recorrer numero ya impreso + Num_Col_Pos = Num_Col_Pos - 2; + lcd.setCursor (Num_Col_Pos, Num_Row_Pos); + lcd.print (Num_Val_Temp_1); + lcd.print (Num_Val_Temp_2); + // dibujar numero nuevo + Num_Col_Pos = Num_Col_Pos + 2; + lcd.setCursor (Num_Col_Pos, Num_Row_Pos); + lcd.print (Boton_Calc); + Num_Val = Boton_Calc + (Num_Val_Temp_1 * 100) + (Num_Val_Temp_2 * 10); + } +Salida: + lcd.noBlink(); + // pintar los ceros antes del numero + Numerico_Write (Num_Val, Num_Col_Pos - 2, Num_Row_Pos); + Num_Col_Pos = Num_Col_Pos - 4; + // regresar el cursor a su ligar + lcd.setCursor (Num_Col_Pos, Num_Row_Pos); +Salida_Option: + { + lcd.noBlink(); + lcd.setCursor (Num_Col_Pos, Num_Row_Pos); + delay(300); // rebote de boton + } +} + +void Numerico_Read() +{ + long Num_Barrido_Time = 5; // tiempo entre barrido de keys + Boton_Calc = 17; // limpiar valor para lectura + while (Boton_Calc == 17) // valor calculado # E * F, 17 sin valor calculado + { + // Barrido + // Linea 1 + digitalWrite(Boton_Array_1, LOW); // lectura linea 1 + // Lectura 1A = 1 + if (digitalRead(Boton_Array_A) == LOW) + { + Boton_Calc = 1; + delay(Boton_Delay_Teclado); + } + delay(Num_Barrido_Time); + // Lectura 1B = 6 + if (digitalRead(Boton_Array_B) == LOW) + { + Boton_Calc = 4; + delay(Boton_Delay_Teclado); + } + delay(Num_Barrido_Time); + // Lectura 1C = 7 + if (digitalRead(Boton_Array_C) == LOW) + { + Boton_Calc = 7; + delay(Boton_Delay_Teclado); + } + delay(Num_Barrido_Time); + // Lectura 1D = * = 15 + if (digitalRead(Boton_Array_D) == LOW) + { + Boton_Calc = 15; + delay(Boton_Delay_Teclado); + } + delay(Num_Barrido_Time); + digitalWrite(Boton_Array_1, HIGH); // lectura linea 1 + + // Linea 2 + digitalWrite(Boton_Array_2, LOW); // lectura linea 2 + // Lectura 2A = 2 + if (digitalRead(Boton_Array_A) == LOW) + { + Boton_Calc = 2; + delay(Boton_Delay_Teclado); + } + delay(Num_Barrido_Time); + // Lectura 2B = 5 + if (digitalRead(Boton_Array_B) == LOW) + { + Boton_Calc = 5; + delay(Boton_Delay_Teclado); + } + delay(Num_Barrido_Time); + // Lectura 2C = 8 + if (digitalRead(Boton_Array_C) == LOW) + { + Boton_Calc = 8; + delay(Boton_Delay_Teclado); + } + delay(Num_Barrido_Time); + // Lectura 2D = 0 + if (digitalRead(Boton_Array_D) == LOW) + { + Boton_Calc = 0; + delay(Boton_Delay_Teclado); + } + delay(Num_Barrido_Time); + digitalWrite(Boton_Array_2, HIGH); // lectura linea 2 + + // Linea 3 + digitalWrite(Boton_Array_3, LOW); // lectura linea 3 + // Lectura 3A = 3 + if (digitalRead(Boton_Array_A) == LOW) + { + Boton_Calc = 3; + delay(Boton_Delay_Teclado); + } + delay(Num_Barrido_Time); + // Lectura 3B = 4 + if (digitalRead(Boton_Array_B) == LOW) + { + Boton_Calc = 6; + delay(Boton_Delay_Teclado); + } + delay(Num_Barrido_Time); + // Lectura 3C = 9 + if (digitalRead(Boton_Array_C) == LOW) + { + Boton_Calc = 9; + delay(Boton_Delay_Teclado); + } + delay(Num_Barrido_Time); + // Lectura 3D = 14 + if (digitalRead(Boton_Array_D) == LOW) + { + Boton_Calc = 14; + delay(Boton_Delay_Teclado); + } + delay(Num_Barrido_Time); + digitalWrite(Boton_Array_3, HIGH); // lectura linea 3 + + // Linea 4 + digitalWrite(Boton_Array_4, LOW); // lectura linea 4 + // Lectura 4A = 10 + if (digitalRead(Boton_Array_A) == LOW) + { + Boton_Calc = 10; + delay(Boton_Delay_Teclado); + } + delay(Num_Barrido_Time); + // Lectura 4B = 11 + if (digitalRead(Boton_Array_B) == LOW) + { + Boton_Calc = 11; + delay(Boton_Delay_Teclado); + } + delay(Num_Barrido_Time); + // Lectura 4C = 12 + if (digitalRead(Boton_Array_C) == LOW) + { + Boton_Calc = 12; + delay(Boton_Delay_Teclado); + } + delay(Num_Barrido_Time); + // Lectura 4D = 13 + if (digitalRead(Boton_Array_D) == LOW) + { + Boton_Calc = 13; + delay(Boton_Delay_Teclado); + } + delay(Num_Barrido_Time); + digitalWrite(Boton_Array_4, HIGH); // lectura linea 4 + + // Cursor center "enter" + if (digitalRead(Boton_Center) == LOW) + { + Boton_Calc = 14; + delay(Boton_Delay_Teclado); + } + } +} + +void Analog_Read_DMX(byte col, byte row) +{ + // escritura del numero desde el encoder aplica a dmx + lcd.setCursor (col - 1, row); + lcd.print("a"); // indicar que es analogo + // escribir el valor anterior + Numerico_Write(DMX_Values[Canal_Actual], col, row); + lcd.setCursor (col - 1, row); + lcd.blink(); + // lectura de bton de teclado + digitalWrite(Boton_Array_3, LOW); // lectura linea 3 + // lectura de encoder + long read; + long read_ant = myEnc.read() / 4; // 4 porque la libreria muestra 4 numeros en cada paso + long numero = DMX_Values[Canal_Actual]; + while (digitalRead(Boton_Array_D) == HIGH && digitalRead(Boton_Center) == HIGH) // enter y center para paro + { + // lectura de encoder + read = myEnc.read() / 4; // / 4 porque la libreria muestra 4 numeros en cada paso + if (read != read_ant) + { + // restar sumar + if (read < read_ant) // restar + { + numero = numero - 1; + } + if (read > read_ant) // sumar + { + numero = numero + 1; + } + // limites + if (numero < 0) + { + numero = 255; + } + if (numero > 255) + { + numero = 0; + } + // escribir el valor + Numerico_Write(numero, col, row); + lcd.setCursor (col - 1, row); + ArduinoDmx0.TxBuffer[Canal_Actual - 1] = numero; + DMX_Values[Canal_Actual] = numero; + read_ant = read; + } + } + lcd.noBlink(); + digitalWrite(Boton_Array_3, HIGH); // lectura linea 3 + delay(300); // delay para salir de la lectura analoga +} \ No newline at end of file From a3251d414d2ed1b7b9dd11f653e7afc1d648d629 Mon Sep 17 00:00:00 2001 From: Daniel Becerril Date: Sat, 1 Aug 2020 18:59:04 -0500 Subject: [PATCH 2/2] Update README.md --- README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3f08b55..41b7048 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## **Firmware - LCD 20x4** -[![version](https://img.shields.io/badge/version-1.5_release-brightgreen.svg)](CHANGELOG.md) +[![version](https://img.shields.io/badge/version-1.6_release-brightgreen.svg)](CHANGELOG.md) [![license](https://img.shields.io/badge/licence-GNU_GPL_v3.0-blue)](https://github.com/Arduino-DMX-512-Tester-and-Controller/Arduino-DMX-512-Tester-and-Controller-LCD-20x4-Firmware/blob/master/LICENCE.md) ![GitHub issues](https://img.shields.io/github/issues/Arduino-DMX-512-Tester-and-Controller/Arduino-DMX-512-Tester-and-Controller-LCD-20x4-Firmware) @@ -90,14 +90,20 @@ Herramienta Open Hardware, para pruebas y control de iluminación de espectácul ### ![**Changelog**](CHANGELOG.md) -- Ultima versión con potenciómetro -- **CORREGIDO,** el cursor en el análogo se mostraba el blink fuera del numero y se encimaba +- **CORREGIDO,** se agrega un encoder KEYES Rotary encoder module KY-040 para remplazar el potenciómetro +- **AGREGADO,** el botón del centro es el mismo del encoder +- **AGREGADO,** encoder CLK en 6 DT en 7 +- **CORREGIDO,** el pin del potenciómetro se elimina +- **AGREGADO,** encoder library + - https://www.pjrc.com/teensy/td_libs_Encoder.html +- **CORREGIDO,** lectura análoga de valor, se agrega el valor anterior en la escritura del LCD +- **CORREGIDO,** lectura análoga en valor el cursor blink se queda en la "a" y no sobre el numero *** ### ![**Hardware**](https://github.com/Arduino-DMX-512-Tester-and-Controller/Arduino-DMX-512-Tester-and-Controller-LCD-20x4-Hardware) -- v0.3 a v0.4 +- v0.5 a v0.6 ***