#include <Arduino.h>
#include "timer_System.h"
#include "inps_manager.h"
#include "asciitohex.h"
#include "pot_manager.h"
/////////////////////////////////////////////////////////////////////
#define TOTAL_DIGITS 3
#define VIEW_MENU 1
#define INC_MENU 2
#define DEC_MENU 3
#define POT1 0
/////////////////////////////////////////////////////////////////////
const int KEY_MENU = 7;
const int KEY_INC = 8;
const int KEY_DEC = 9;
/////////////////////////////////////////////////////////////////////
const int DIGIT_1 = 6;
const int DIGIT_2 = 5;
const int DIGIT_3 = 4;
/////////////////////////////////////////////////////////////////////
const int DATA_SPI = 12;
const int CLOCK_SPI = 11;
const int LOAD_SPI = 10;
/////////////////////////////////////////////////////////////////////
uint8_t count = 16;
//arranca en modo falla
bool oldFaultState = true;
typedef union _FAULTS_STATUS
{
uint8_t value;
struct
{
unsigned ov_fault:1;
unsigned uv_fault:1;
unsigned fs_fault:1;
unsigned extend:5;
}flags;
}FAULTS_STATUS;
FAULTS_STATUS faults_info;
typedef union _MENU_DEVICE
{
uint8_t value;
struct
{
unsigned edit:2; //indica que esta en edicion o supervision
unsigned param_sel:3; //puntero para el desplazamiento
unsigned peram_edit:1; //indica que esta editando el parametro
unsigned blinK_dsp:1; //para indicar edicion
unsigned extend:1; //para expandir
}flags;
}MENU_DEVICE;
MENU_DEVICE info_menu;
const uint16_t thresoldLow[3] = {85, 125, 5};
const uint16_t thresoldHigh[3] = {115, 140, 300};
uint16_t thresoldValue[3] = {100, 140, 20};
uint16_t paramToView[3] = {0};
uint16_t pot1;
/////////////////////////////////////////////////////////////////////
void failProcess(uint8_t value);
void checkInputKeys(void);
void vProcessKeys(uint8_t sel);
void decimal_to_bcd(uint16_t decimal);
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
void SetTimer1()
{
cli(); //stop interrupts
//set timer1 interrupt at 120Hz
TCCR1A = 0;// set entire TCCR1A register to 0
TCCR1B = 0;// same for TCCR1B
TCNT1 = 0;//initialize counter value to 0
// set compare match register for 60hz increments
OCR1A = 10000; // = (16*10^6) / (120 * 8) - 1 (must be <65536) //60Hz 16683
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS10 and CS12 bits for 1024 prescaler
//TCCR1B |= (1 << CS12) | (1 << CS10);
// Set CS11 bit for 8 prescaler
TCCR1B |= (1 << CS11);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
sei(); //allow interrupts
}
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
ISR(TIMER1_COMPA_vect)
{
flagTickBase = 1;
TimersSys_Tick();
inpManager_Refresh();
}
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
void setup()
{
SetTimer1();
/////////////////////////////////////////////////////////////////////
TimersSys_Init(); // Inicializa la estructuras de los 4 timers del sistema, en el header de la libreria
TimersSys_Start(0, 10); // Inicializa 0 de TimerSys, de calibración 100 ms
TimersSys_Start(1, 25); // Inicializa 1 de TimersSys: 250ms (25 * Tick de TMR2(10ms))
TimersSys_Start(2, 3); // Inicializa 2 de TimersSys: 30ms (3 * Tick de TMR2(10ms))
TimersSys_Start(3, 50); // Inicializa 2 de TimersSys: 30ms (3 * Tick de TMR2(10ms))
inpsManager_Init();
inpsManager_Cfg(0, KEY_MENU, INPUT_PULLUP);
inpsManager_Cfg(1, KEY_INC, INPUT_PULLUP);
inpsManager_Cfg(2, KEY_DEC, INPUT_PULLUP);
/////////////////////////////////////////////////////////////////////
potManager_Init(); //inicializa las estructuras de potenciometro
potManager_CfgPot(POT1, A1); //
/////////////////////////////////////////////////////////////////////
Serial.begin(115200);
// put your setup code here, to run once:
/*pinMode(KEY_MENU, INPUT_PULLUP);
pinMode(KEY_INC, INPUT_PULLUP);*/
/////////////////////////////////////////////////////////////////////
pinMode(DIGIT_1, OUTPUT);
pinMode(DIGIT_2, OUTPUT);
pinMode(DIGIT_3, OUTPUT);
pinMode(LOAD_SPI, OUTPUT);
pinMode(CLOCK_SPI, OUTPUT);
pinMode(DATA_SPI, OUTPUT);
digitalWrite(DIGIT_1, HIGH);
digitalWrite(DIGIT_2, HIGH);
digitalWrite(DIGIT_3, HIGH);
/////////////////////////////////////////////////////////////////////
info_menu.value = 0;
faults_info.value = 0; //deberia arrancar con falla de voltaje
oldFaultState = true;
faults_info.flags.uv_fault = 1;
/////////////////////////////////////////////////////////////////////
}
void loop()
{
//////////////////////////////////////////////
if (TIMERSYS_CHECK_EVENT(0)) // 100 ms
{
TIMERSYS_CLEAR_EVENT(0);
checkInputKeys( );
//Serial.print(pot1, DEC);
//Serial.println("");
}
//llevar esta a 50 ms
if (TIMERSYS_CHECK_EVENT(1)) // 250 ms
{
TIMERSYS_CLEAR_EVENT(1);
}
if (TIMERSYS_CHECK_EVENT(2)) //30ms
{
TIMERSYS_CLEAR_EVENT(2);
///////////////////////////////////////////////////////
pot1 = (potManager_fastRefresh(POT1) >> 2); //trunca a 8 bits
failProcess(pot1);
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
if(++count >= TOTAL_DIGITS){
count = 0;
}
if(info_menu.flags.edit == 0)
{
if(faults_info.value == 0)
{
decimal_to_bcd(pot1);
digitSelect(count, SevenSegmentASCII[paramToView[count]]);
}
else
{
digitSelect(count, ErrTable[faults_info.value][count]);
}
}
else if(info_menu.flags.edit == 1)
{
digitSelect(count, MenutoDisplay[info_menu.flags.param_sel - 1][count]);
}
else if(info_menu.flags.edit == 2)
{
decimal_to_bcd(thresoldValue[info_menu.flags.param_sel - 1]);
digitSelect(count, SevenSegmentASCII[paramToView[count]]);
}
///////////////////////////////////////////////////////
}
if (TIMERSYS_CHECK_EVENT(3)) //500s
{
TIMERSYS_CLEAR_EVENT(3);
if(info_menu.flags.blinK_dsp == 0)
{
info_menu.flags.blinK_dsp = 1;
}
else
{
info_menu.flags.blinK_dsp = 0;
}
}
}
void checkInputKeys( )
{
if(inpsInfo[0].b.change == 1)
{
inpsInfo[0].b.change = 0;
if(!GET_INP_STATE(0))
{
vProcessKeys(VIEW_MENU);
}
}
if(inpsInfo[1].b.change == 1)
{
inpsInfo[1].b.change = 0;
if(!GET_INP_STATE(1))
{
vProcessKeys(INC_MENU);
//Serial.println("INC");
}
}
if(inpsInfo[2].b.change == 1)
{
inpsInfo[2].b.change = 0;
if(!GET_INP_STATE(2))
{
vProcessKeys(DEC_MENU);
//Serial.println("DEC");
}
}
}
void failProcess(uint8_t value)
{
//Procesamiento de falla //
if(value < thresoldValue[0]) //low voltage
{
faults_info.flags.uv_fault = 1;
}
else if(value > thresoldValue[1]) //high voltage
{
faults_info.flags.ov_fault = 1;
}
else
{
faults_info.value = 0;
}
}
void digitSelect(uint8_t select, uint8_t value)
{
digitalWrite(DIGIT_1, HIGH);
digitalWrite(DIGIT_2, HIGH);
digitalWrite(DIGIT_3, HIGH);
if(info_menu.flags.blinK_dsp == 1 && info_menu.flags.edit == 2)
{
return;
}
///////////////////////////////////////////////////////////////////////////////
digitalWrite(LOAD_SPI, LOW);
shiftOut(DATA_SPI, CLOCK_SPI, MSBFIRST, value);
digitalWrite(LOAD_SPI, HIGH);
///////////////////////////////////////////////////////////////////////////////
switch(select)
{
case 0:
digitalWrite(DIGIT_3, LOW);
break;
case 1:
digitalWrite(DIGIT_2, LOW);
break;
case 2:
digitalWrite(DIGIT_1, LOW);
break;
default:
return;
}
}
void vProcessKeys(uint8_t sel)
{
if(sel == VIEW_MENU)
{
if(info_menu.flags.edit == 0)
{
info_menu.flags.edit = 1;
info_menu.flags.param_sel = 1;
}
else if(info_menu.flags.edit == 1)
{
info_menu.flags.edit = 2;
}
else
{
info_menu.flags.edit = 0;
}
return;
}
if(sel == INC_MENU)
{
if(info_menu.flags.edit == 1)
{
if(++info_menu.flags.param_sel > 3)
{
info_menu.flags.param_sel = 0;
info_menu.flags.edit = 0;
}
}
else if(info_menu.flags.edit == 2)
{
if(++thresoldValue[info_menu.flags.param_sel -1] > thresoldHigh[info_menu.flags.param_sel -1])
{
thresoldValue[info_menu.flags.param_sel -1] = thresoldLow[info_menu.flags.param_sel -1];
}
}
}
if(sel == DEC_MENU)
{
if(info_menu.flags.edit == 2)
{
if(--thresoldValue[info_menu.flags.param_sel -1] < thresoldLow[info_menu.flags.param_sel -1])
{
thresoldValue[info_menu.flags.param_sel -1] = thresoldHigh[info_menu.flags.param_sel -1];
}
}
}
}
// Función para convertir decimal a BCD sin usar divisiones
void decimal_to_bcd(uint16_t decimal)
{
// Limitar el rango a 0-999
if (decimal > 999) decimal = 999;
///uint8_t hundreds = 0, tens = 0, units = 0;
paramToView[2] = paramToView[1] = paramToView[0] = 16;
// Calcular centenas (resta iterativa)
while (decimal >= 100) {
decimal -= 100;
paramToView[2]++;
}
// Calcular decenas (resta iterativa)
while (decimal >= 10) {
decimal -= 10;
paramToView[1]++;
}
// El restante son las unidades
paramToView[0] += decimal;
}