#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdarg.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/i2c.h"
#include "esp_rom_sys.h"
#include "nvs_flash.h"
#include "nvs.h"
// ======================================================
// 74HC165 - ENTRADAS
// ======================================================
#define PIN_165_DATA GPIO_NUM_34
#define PIN_165_CLOCK GPIO_NUM_25
#define PIN_165_LOAD GPIO_NUM_26
// ======================================================
// 74HC595 - SALIDAS
// ======================================================
#define PIN_595_DATA GPIO_NUM_27
#define PIN_595_CLOCK GPIO_NUM_32
#define PIN_595_LATCH GPIO_NUM_33
// ======================================================
// ZUMBADOR
// ======================================================
#define PIN_BUZZER GPIO_NUM_23
// ======================================================
// LCD
// ======================================================
#define I2C_PORT I2C_NUM_0
#define I2C_SDA GPIO_NUM_21
#define I2C_SCL GPIO_NUM_22
#define LCD_ADDR 0x27
#define LCD_RS 0x01
#define LCD_EN 0x04
#define LCD_BL 0x08
// ======================================================
// PRODUCTOS
// ======================================================
#define PRODUCTO_RANCHO 1
#define PRODUCTO_PLATINUM 2
#define PRODUCTO_SANJUAN 3
#define PRODUCTO_ROJO 4
#define PRECIO_RANCHO 30
#define PRECIO_PLATINUM 35
#define PRECIO_SANJUAN 40
#define PRECIO_ROJO 35
// ======================================================
// SALIDAS LOCKER 1
// ======================================================
// 74HC595 #1 Q0
#define OUT_ROJO_L1 0
// 74HC595 #1 Q1
#define OUT_VERDE_L1 1
// 74HC595 #3 Q4
#define OUT_AZUL_L1 20
uint32_t estadoSalidas = 0;
// ======================================================
// VARIABLES GENERALES
// ======================================================
int saldo = 0;
int sobranteExtra = 0;
int ventasRealizadas = 0;
// El locker conserva el producto asignado
// aunque la charola se retire.
int productoLocker1 = PRODUCTO_RANCHO;
// ======================================================
// ESTADOS ANTERIORES BOTONES
// ======================================================
bool antRancho = true;
bool antPlatinum = true;
bool antSanJuan = true;
bool antRojo = true;
bool antSi = true;
bool antNo = true;
bool antMoneda1 = true;
bool antMoneda2 = true;
bool antMoneda5 = true;
bool antMoneda10 = true;
// ======================================================
// UTILIDAD
// ======================================================
static void delay_us(uint32_t us)
{
esp_rom_delay_us(us);
}
// ======================================================
// CATÁLOGO
// ======================================================
const char *nombreProducto(int producto)
{
switch (producto) {
case PRODUCTO_RANCHO:
return "RANCHO";
case PRODUCTO_PLATINUM:
return "PLATINUM";
case PRODUCTO_SANJUAN:
return "SAN JUAN";
case PRODUCTO_ROJO:
return "ROJO";
default:
return "DESCONOCIDO";
}
}
int precioProducto(int producto)
{
switch (producto) {
case PRODUCTO_RANCHO:
return PRECIO_RANCHO;
case PRODUCTO_PLATINUM:
return PRECIO_PLATINUM;
case PRODUCTO_SANJUAN:
return PRECIO_SANJUAN;
case PRODUCTO_ROJO:
return PRECIO_ROJO;
default:
return 0;
}
}
// ======================================================
// BUZZER
// ======================================================
void beep(int ms)
{
int ciclos = ms * 2;
for (int i = 0; i < ciclos; i++) {
gpio_set_level(
PIN_BUZZER,
1
);
delay_us(250);
gpio_set_level(
PIN_BUZZER,
0
);
delay_us(250);
}
}
void beepDoble(void)
{
beep(70);
vTaskDelay(
pdMS_TO_TICKS(70)
);
beep(70);
}
// ======================================================
// 74HC595
// ======================================================
void actualizar595(void)
{
gpio_set_level(
PIN_595_LATCH,
0
);
for (int i = 31; i >= 0; i--) {
bool bit =
(
estadoSalidas >>
i
)
& 0x01;
gpio_set_level(
PIN_595_DATA,
bit
);
gpio_set_level(
PIN_595_CLOCK,
1
);
delay_us(2);
gpio_set_level(
PIN_595_CLOCK,
0
);
}
gpio_set_level(
PIN_595_LATCH,
1
);
delay_us(2);
gpio_set_level(
PIN_595_LATCH,
0
);
}
void salida595(
int numero,
bool estado
)
{
if (estado) {
estadoSalidas |=
(
(uint32_t)1
<< numero
);
} else {
estadoSalidas &=
~(
(uint32_t)1
<< numero
);
}
actualizar595();
}
// ======================================================
// 74HC165
// ======================================================
uint32_t leer165(void)
{
uint32_t datos = 0;
gpio_set_level(
PIN_165_LOAD,
0
);
delay_us(5);
gpio_set_level(
PIN_165_LOAD,
1
);
delay_us(5);
for (int i = 0; i < 32; i++) {
datos <<= 1;
if (
gpio_get_level(
PIN_165_DATA
)
) {
datos |= 1;
}
gpio_set_level(
PIN_165_CLOCK,
1
);
delay_us(2);
gpio_set_level(
PIN_165_CLOCK,
0
);
delay_us(2);
}
return datos;
}
bool entrada165(
uint32_t datos,
int chip,
int entrada
)
{
int bit =
(
(chip - 1)
* 8
)
+ entrada;
return
(
datos >>
bit
)
& 0x01;
}
// ======================================================
// LCD BAJO NIVEL
// ======================================================
esp_err_t lcd_i2c_write(
uint8_t data
)
{
return i2c_master_write_to_device(
I2C_PORT,
LCD_ADDR,
&data,
1,
pdMS_TO_TICKS(100)
);
}
void lcd_pulso(
uint8_t data
)
{
lcd_i2c_write(
data | LCD_EN
);
delay_us(1);
lcd_i2c_write(
data & ~LCD_EN
);
delay_us(50);
}
void lcd_nibble(
uint8_t nibble,
uint8_t modo
)
{
uint8_t data =
(
nibble & 0xF0
)
|
modo
|
LCD_BL;
lcd_i2c_write(
data
);
lcd_pulso(
data
);
}
void lcd_send(
uint8_t valor,
uint8_t modo
)
{
lcd_nibble(
valor & 0xF0,
modo
);
lcd_nibble(
(valor << 4) & 0xF0,
modo
);
}
void lcd_cmd(
uint8_t comando
)
{
lcd_send(
comando,
0
);
if (
comando == 0x01 ||
comando == 0x02
) {
vTaskDelay(
pdMS_TO_TICKS(2)
);
}
}
void lcd_char(
char c
)
{
lcd_send(
(uint8_t)c,
LCD_RS
);
}
void lcd_print(
const char *texto
)
{
while (*texto) {
lcd_char(
*texto
);
texto++;
}
}
void lcd_cursor(
int columna,
int fila
)
{
static const uint8_t offsets[] = {
0x00,
0x40,
0x14,
0x54
};
lcd_cmd(
0x80 |
(
offsets[fila]
+ columna
)
);
}
void lcd_clear(void)
{
lcd_cmd(
0x01
);
vTaskDelay(
pdMS_TO_TICKS(2)
);
}
// ======================================================
// LÍNEA LCD SEGURA
// ======================================================
void lcd_linea(
int fila,
const char *formato,
...
)
{
char temporal[64];
char salida[21];
va_list args;
va_start(
args,
formato
);
vsnprintf(
temporal,
sizeof(temporal),
formato,
args
);
va_end(args);
memset(
salida,
' ',
20
);
salida[20] = '\0';
size_t longitud =
strlen(
temporal
);
if (longitud > 20) {
longitud = 20;
}
memcpy(
salida,
temporal,
longitud
);
lcd_cursor(
0,
fila
);
lcd_print(
salida
);
}
void lcd_init_hw(void)
{
vTaskDelay(
pdMS_TO_TICKS(50)
);
lcd_nibble(
0x30,
0
);
vTaskDelay(
pdMS_TO_TICKS(5)
);
lcd_nibble(
0x30,
0
);
delay_us(150);
lcd_nibble(
0x30,
0
);
lcd_nibble(
0x20,
0
);
lcd_cmd(0x28);
lcd_cmd(0x0C);
lcd_cmd(0x06);
lcd_clear();
}
// ======================================================
// MEMORIA
// ======================================================
void guardarProductoLocker(void)
{
nvs_handle_t handle;
if (
nvs_open(
"mihueveria",
NVS_READWRITE,
&handle
)
==
ESP_OK
) {
nvs_set_i32(
handle,
"producto_l1",
productoLocker1
);
nvs_commit(
handle
);
nvs_close(
handle
);
}
}
void cargarProductoLocker(void)
{
nvs_handle_t handle;
int32_t valor =
PRODUCTO_RANCHO;
if (
nvs_open(
"mihueveria",
NVS_READONLY,
&handle
)
==
ESP_OK
) {
nvs_get_i32(
handle,
"producto_l1",
&valor
);
nvs_close(
handle
);
}
if (
valor < PRODUCTO_RANCHO ||
valor > PRODUCTO_ROJO
) {
valor =
PRODUCTO_RANCHO;
}
productoLocker1 =
(int)valor;
}
// ======================================================
// PANTALLA PRINCIPAL
// ======================================================
void pantallaInicio(void)
{
lcd_clear();
lcd_linea(
0,
"MI HUEVERIA"
);
lcd_linea(
1,
"Saldo: $%d",
saldo
);
lcd_linea(
2,
"R30 P35 SJ40 Ro35"
);
if (saldo == 0) {
lcd_linea(
3,
"No damos cambio"
);
} else {
lcd_linea(
3,
"Elija su huevo"
);
}
}
void actualizarSaldoLCD(void)
{
lcd_linea(
1,
"Saldo: $%d",
saldo
);
lcd_linea(
3,
"Elija su huevo"
);
}
// ======================================================
// MONEDAS
// ======================================================
void registrarMoneda(
int valor
)
{
saldo += valor;
beep(40);
actualizarSaldoLCD();
printf(
"MONEDA +$%d / SALDO $%d\n",
valor,
saldo
);
}
// ======================================================
// FINALIZAR SOBRANTE
// ======================================================
void finalizarSobrante(void)
{
int sobrante =
saldo;
sobranteExtra +=
sobrante;
saldo = 0;
lcd_clear();
lcd_linea(
0,
"Operacion terminada"
);
lcd_linea(
1,
"Saldo restante:$%d",
sobrante
);
lcd_linea(
2,
"Gracias por comprar"
);
lcd_linea(
3,
"Mi Hueveria"
);
printf(
"SOBRANTE CLIENTE: $%d\n",
sobrante
);
printf(
"SOBRANTE ACUMULADO: $%d\n",
sobranteExtra
);
beepDoble();
vTaskDelay(
pdMS_TO_TICKS(2500)
);
pantallaInicio();
}
// ======================================================
// PREGUNTAR SALDO SOBRANTE
// ======================================================
void preguntarSaldoRestante(void)
{
int segundos = 60;
uint32_t inicial =
leer165();
antSi =
entrada165(
inicial,
4,
0
);
antNo =
entrada165(
inicial,
4,
1
);
while (
segundos > 0
) {
lcd_clear();
lcd_linea(
0,
"Saldo restante:$%d",
saldo
);
lcd_linea(
1,
"No damos cambio"
);
lcd_linea(
2,
"Comprar mas huevo?"
);
lcd_linea(
3,
"SI / NO %02ds",
segundos
);
for (
int i = 0;
i < 20;
i++
) {
uint32_t datos =
leer165();
bool si =
entrada165(
datos,
4,
0
);
bool no =
entrada165(
datos,
4,
1
);
// SI
if (
antSi &&
!si
) {
beep(50);
lcd_clear();
lcd_linea(
0,
"Saldo conservado"
);
lcd_linea(
1,
"Disponible: $%d",
saldo
);
lcd_linea(
2,
"Agregue monedas o"
);
lcd_linea(
3,
"elija otro huevo"
);
vTaskDelay(
pdMS_TO_TICKS(
1800
)
);
pantallaInicio();
return;
}
// NO
if (
antNo &&
!no
) {
beep(50);
finalizarSobrante();
return;
}
antSi =
si;
antNo =
no;
vTaskDelay(
pdMS_TO_TICKS(50)
);
}
segundos--;
}
lcd_clear();
lcd_linea(
0,
"Tiempo finalizado"
);
lcd_linea(
1,
"Cerrando operacion"
);
lcd_linea(
2,
"Saldo pasa a"
);
lcd_linea(
3,
"sobrante"
);
vTaskDelay(
pdMS_TO_TICKS(1200)
);
finalizarSobrante();
}
// ======================================================
// ADMIN
// ======================================================
void modoAdmin(void)
{
int seleccion =
productoLocker1;
uint32_t inicial =
leer165();
bool aRancho =
entrada165(
inicial,
3,
4
);
bool aPlatinum =
entrada165(
inicial,
3,
5
);
bool aSanJuan =
entrada165(
inicial,
3,
6
);
bool aRojo =
entrada165(
inicial,
3,
7
);
bool aSi =
entrada165(
inicial,
4,
0
);
bool aNo =
entrada165(
inicial,
4,
1
);
while (1) {
lcd_clear();
lcd_linea(
0,
"ADMIN - LOCKER 1"
);
lcd_linea(
1,
"Producto asignado:"
);
lcd_linea(
2,
"%s $%d",
nombreProducto(
seleccion
),
precioProducto(
seleccion
)
);
lcd_linea(
3,
"SI guarda / NO sale"
);
while (1) {
uint32_t datos =
leer165();
bool rancho =
entrada165(
datos,
3,
4
);
bool platinum =
entrada165(
datos,
3,
5
);
bool sanJuan =
entrada165(
datos,
3,
6
);
bool rojo =
entrada165(
datos,
3,
7
);
bool si =
entrada165(
datos,
4,
0
);
bool no =
entrada165(
datos,
4,
1
);
if (
aRancho &&
!rancho
) {
seleccion =
PRODUCTO_RANCHO;
beep(40);
break;
}
if (
aPlatinum &&
!platinum
) {
seleccion =
PRODUCTO_PLATINUM;
beep(40);
break;
}
if (
aSanJuan &&
!sanJuan
) {
seleccion =
PRODUCTO_SANJUAN;
beep(40);
break;
}
if (
aRojo &&
!rojo
) {
seleccion =
PRODUCTO_ROJO;
beep(40);
break;
}
if (
aSi &&
!si
) {
productoLocker1 =
seleccion;
guardarProductoLocker();
beepDoble();
lcd_clear();
lcd_linea(
0,
"LOCKER 1 GUARDADO"
);
lcd_linea(
1,
"%s $%d",
nombreProducto(
productoLocker1
),
precioProducto(
productoLocker1
)
);
lcd_linea(
2,
"Asignacion lista"
);
lcd_linea(
3,
"Puede resurtir"
);
vTaskDelay(
pdMS_TO_TICKS(
1800
)
);
return;
}
if (
aNo &&
!no
) {
beep(40);
lcd_clear();
lcd_linea(
1,
"Sin cambios"
);
vTaskDelay(
pdMS_TO_TICKS(
1000
)
);
return;
}
aRancho =
rancho;
aPlatinum =
platinum;
aSanJuan =
sanJuan;
aRojo =
rojo;
aSi =
si;
aNo =
no;
vTaskDelay(
pdMS_TO_TICKS(30)
);
}
uint32_t refresco =
leer165();
aRancho =
entrada165(
refresco,
3,
4
);
aPlatinum =
entrada165(
refresco,
3,
5
);
aSanJuan =
entrada165(
refresco,
3,
6
);
aRojo =
entrada165(
refresco,
3,
7
);
aSi =
entrada165(
refresco,
4,
0
);
aNo =
entrada165(
refresco,
4,
1
);
}
}
// ======================================================
// INTENTAR COMPRA
// ======================================================
void intentarCompra(
int producto,
bool hayCharola,
bool puertaCerrada
)
{
int precio =
precioProducto(
producto
);
// Locker no tiene ese producto.
if (
productoLocker1 !=
producto
) {
lcd_clear();
lcd_linea(
0,
"No disponible aqui"
);
lcd_linea(
1,
"%s",
nombreProducto(
producto
)
);
lcd_linea(
2,
"Pruebe otra opcion"
);
lcd_linea(
3,
"Saldo conservado"
);
beep(100);
vTaskDelay(
pdMS_TO_TICKS(1600)
);
pantallaInicio();
return;
}
// No hay charola.
if (!hayCharola) {
lcd_clear();
lcd_linea(
0,
"Producto agotado"
);
lcd_linea(
1,
"%s",
nombreProducto(
producto
)
);
lcd_linea(
2,
"Saldo conservado"
);
lcd_linea(
3,
"Elija otra opcion"
);
beep(200);
vTaskDelay(
pdMS_TO_TICKS(1600)
);
pantallaInicio();
return;
}
// Puerta abierta.
if (!puertaCerrada) {
lcd_clear();
lcd_linea(
0,
"Puerta abierta"
);
lcd_linea(
1,
"Cierre Locker 1"
);
lcd_linea(
2,
"Saldo conservado"
);
beep(250);
vTaskDelay(
pdMS_TO_TICKS(1600)
);
pantallaInicio();
return;
}
// Saldo insuficiente.
if (
saldo <
precio
) {
lcd_clear();
lcd_linea(
0,
"Saldo insuficiente"
);
lcd_linea(
1,
"Precio: $%d",
precio
);
lcd_linea(
2,
"Saldo: $%d",
saldo
);
lcd_linea(
3,
"Faltan: $%d",
precio - saldo
);
beep(80);
vTaskDelay(
pdMS_TO_TICKS(1800)
);
pantallaInicio();
return;
}
// ==================================================
// COBRAR
// ==================================================
saldo -=
precio;
ventasRealizadas++;
printf(
"VENTA %s $%d\n",
nombreProducto(
producto
),
precio
);
// ==================================================
// ABRIR LOCKER
// ==================================================
lcd_clear();
lcd_linea(
0,
"PAGO ACEPTADO"
);
lcd_linea(
1,
"%s $%d",
nombreProducto(
producto
),
precio
);
lcd_linea(
2,
"Abra Locker 1"
);
lcd_linea(
3,
"Retire su charola"
);
// Verde:
// identifica el locker.
salida595(
OUT_VERDE_L1,
true
);
// Azul:
// cerradura energizada.
salida595(
OUT_AZUL_L1,
true
);
beepDoble();
vTaskDelay(
pdMS_TO_TICKS(3000)
);
// Cerradura deja de energizarse.
salida595(
OUT_AZUL_L1,
false
);
// ==================================================
// ESPERAR QUE SAQUEN CHAROLA
// ==================================================
bool retirada =
false;
lcd_linea(
3,
"Esperando retiro..."
);
// 60 segundos.
for (
int i = 0;
i < 1200;
i++
) {
uint32_t datos =
leer165();
bool presente =
entrada165(
datos,
1,
0
);
if (!presente) {
retirada =
true;
break;
}
vTaskDelay(
pdMS_TO_TICKS(50)
);
}
if (!retirada) {
salida595(
OUT_VERDE_L1,
false
);
lcd_clear();
lcd_linea(
0,
"Charola no retirada"
);
lcd_linea(
1,
"Revise Locker 1"
);
lcd_linea(
2,
"Operacion detenida"
);
beep(400);
vTaskDelay(
pdMS_TO_TICKS(1800)
);
pantallaInicio();
return;
}
// ==================================================
// VACÍO
// ==================================================
salida595(
OUT_ROJO_L1,
true
);
lcd_clear();
lcd_linea(
0,
"Charola retirada"
);
lcd_linea(
1,
"Cierre la puerta"
);
lcd_linea(
2,
"Locker 1"
);
// ==================================================
// ESPERAR CIERRE DE PUERTA
// ==================================================
bool cerrada =
false;
for (
int i = 0;
i < 1200;
i++
) {
uint32_t datos =
leer165();
bool puerta =
entrada165(
datos,
1,
1
);
if (puerta) {
cerrada =
true;
break;
}
vTaskDelay(
pdMS_TO_TICKS(50)
);
}
salida595(
OUT_VERDE_L1,
false
);
if (!cerrada) {
lcd_clear();
lcd_linea(
0,
"ATENCION"
);
lcd_linea(
1,
"Puerta sigue abierta"
);
lcd_linea(
2,
"Cierre Locker 1"
);
beep(500);
vTaskDelay(
pdMS_TO_TICKS(1800)
);
}
// ==================================================
// COMPRA TERMINADA
// ==================================================
lcd_clear();
lcd_linea(
0,
"COMPRA COMPLETADA"
);
lcd_linea(
1,
"Gracias!"
);
lcd_linea(
2,
"Saldo restante:$%d",
saldo
);
lcd_linea(
3,
"Mi Hueveria"
);
beepDoble();
vTaskDelay(
pdMS_TO_TICKS(1500)
);
if (
saldo > 0
) {
preguntarSaldoRestante();
} else {
pantallaInicio();
}
}
// ======================================================
// GPIO
// ======================================================
void configurarGPIO(void)
{
gpio_reset_pin(
PIN_165_CLOCK
);
gpio_reset_pin(
PIN_165_LOAD
);
gpio_reset_pin(
PIN_165_DATA
);
gpio_reset_pin(
PIN_595_DATA
);
gpio_reset_pin(
PIN_595_CLOCK
);
gpio_reset_pin(
PIN_595_LATCH
);
gpio_reset_pin(
PIN_BUZZER
);
gpio_set_direction(
PIN_165_CLOCK,
GPIO_MODE_OUTPUT
);
gpio_set_direction(
PIN_165_LOAD,
GPIO_MODE_OUTPUT
);
gpio_set_direction(
PIN_165_DATA,
GPIO_MODE_INPUT
);
gpio_set_direction(
PIN_595_DATA,
GPIO_MODE_OUTPUT
);
gpio_set_direction(
PIN_595_CLOCK,
GPIO_MODE_OUTPUT
);
gpio_set_direction(
PIN_595_LATCH,
GPIO_MODE_OUTPUT
);
gpio_set_direction(
PIN_BUZZER,
GPIO_MODE_OUTPUT
);
gpio_set_level(
PIN_165_CLOCK,
0
);
gpio_set_level(
PIN_165_LOAD,
1
);
gpio_set_level(
PIN_595_DATA,
0
);
gpio_set_level(
PIN_595_CLOCK,
0
);
gpio_set_level(
PIN_595_LATCH,
0
);
gpio_set_level(
PIN_BUZZER,
0
);
estadoSalidas =
0;
actualizar595();
}
// ======================================================
// I2C
// ======================================================
void configurarI2C(void)
{
i2c_config_t conf = {
.mode =
I2C_MODE_MASTER,
.sda_io_num =
I2C_SDA,
.scl_io_num =
I2C_SCL,
.sda_pullup_en =
GPIO_PULLUP_ENABLE,
.scl_pullup_en =
GPIO_PULLUP_ENABLE,
.master.clk_speed =
100000
};
i2c_param_config(
I2C_PORT,
&conf
);
i2c_driver_install(
I2C_PORT,
I2C_MODE_MASTER,
0,
0,
0
);
}
// ======================================================
// APP MAIN
// ======================================================
void app_main(void)
{
// ==================================================
// MEMORIA
// ==================================================
esp_err_t ret =
nvs_flash_init();
if (
ret ==
ESP_ERR_NVS_NO_FREE_PAGES
||
ret ==
ESP_ERR_NVS_NEW_VERSION_FOUND
) {
nvs_flash_erase();
nvs_flash_init();
}
cargarProductoLocker();
// ==================================================
// HARDWARE
// ==================================================
configurarGPIO();
configurarI2C();
lcd_init_hw();
// ==================================================
// ARRANQUE
// ==================================================
lcd_clear();
lcd_linea(
0,
"MI HUEVERIA"
);
lcd_linea(
1,
"Iniciando..."
);
lcd_linea(
2,
"Locker 1:"
);
lcd_linea(
3,
"%s $%d",
nombreProducto(
productoLocker1
),
precioProducto(
productoLocker1
)
);
beep(60);
vTaskDelay(
pdMS_TO_TICKS(1500)
);
pantallaInicio();
// ==================================================
// ADMIN
// ==================================================
bool adminContando =
false;
TickType_t inicioAdmin =
0;
// ==================================================
// LOOP PRINCIPAL
// ==================================================
while (1) {
uint32_t datos =
leer165();
// ==================================================
// SENSORES LOCKER
// ==================================================
bool hayCharola =
entrada165(
datos,
1,
0
);
bool puertaCerrada =
entrada165(
datos,
1,
1
);
// ==================================================
// PRODUCTOS
// ==================================================
bool rancho =
entrada165(
datos,
3,
4
);
bool platinum =
entrada165(
datos,
3,
5
);
bool sanJuan =
entrada165(
datos,
3,
6
);
bool rojo =
entrada165(
datos,
3,
7
);
// ==================================================
// CONTROL
// ==================================================
bool admin =
entrada165(
datos,
4,
2
);
// ==================================================
// MONEDAS
// ==================================================
bool moneda1 =
entrada165(
datos,
4,
3
);
bool moneda2 =
entrada165(
datos,
4,
4
);
bool moneda5 =
entrada165(
datos,
4,
5
);
bool moneda10 =
entrada165(
datos,
4,
6
);
// ==================================================
// LED ROJO AUTOMÁTICO
// ==================================================
salida595(
OUT_ROJO_L1,
!hayCharola
);
// ==================================================
// MONEDA $1
// ==================================================
if (
antMoneda1 &&
!moneda1
) {
registrarMoneda(
1
);
}
antMoneda1 =
moneda1;
// ==================================================
// MONEDA $2
// ==================================================
if (
antMoneda2 &&
!moneda2
) {
registrarMoneda(
2
);
}
antMoneda2 =
moneda2;
// ==================================================
// MONEDA $5
// ==================================================
if (
antMoneda5 &&
!moneda5
) {
registrarMoneda(
5
);
}
antMoneda5 =
moneda5;
// ==================================================
// MONEDA $10
// ==================================================
if (
antMoneda10 &&
!moneda10
) {
registrarMoneda(
10
);
}
antMoneda10 =
moneda10;
// ==================================================
// RANCHO
// ==================================================
if (
antRancho &&
!rancho
) {
intentarCompra(
PRODUCTO_RANCHO,
hayCharola,
puertaCerrada
);
}
antRancho =
rancho;
// ==================================================
// PLATINUM
// ==================================================
if (
antPlatinum &&
!platinum
) {
intentarCompra(
PRODUCTO_PLATINUM,
hayCharola,
puertaCerrada
);
}
antPlatinum =
platinum;
// ==================================================
// SAN JUAN
// ==================================================
if (
antSanJuan &&
!sanJuan
) {
intentarCompra(
PRODUCTO_SANJUAN,
hayCharola,
puertaCerrada
);
}
antSanJuan =
sanJuan;
// ==================================================
// ROJO
// ==================================================
if (
antRojo &&
!rojo
) {
intentarCompra(
PRODUCTO_ROJO,
hayCharola,
puertaCerrada
);
}
antRojo =
rojo;
// ==================================================
// ADMIN OCULTO
//
// Solo con saldo $0.
// Mantener 3 segundos.
// ==================================================
if (
saldo == 0 &&
!admin
) {
if (
!adminContando
) {
adminContando =
true;
inicioAdmin =
xTaskGetTickCount();
}
TickType_t tiempo =
xTaskGetTickCount()
-
inicioAdmin;
if (
tiempo >=
pdMS_TO_TICKS(3000)
) {
adminContando =
false;
beepDoble();
lcd_clear();
lcd_linea(
0,
"MODO ADMIN"
);
lcd_linea(
1,
"Suelte boton"
);
// Esperar liberar ADMIN.
while (1) {
uint32_t d =
leer165();
bool a =
entrada165(
d,
4,
2
);
if (a) {
break;
}
vTaskDelay(
pdMS_TO_TICKS(
20
)
);
}
vTaskDelay(
pdMS_TO_TICKS(
250
)
);
modoAdmin();
pantallaInicio();
// Evitar pulsaciones fantasma.
datos =
leer165();
antRancho =
entrada165(
datos,
3,
4
);
antPlatinum =
entrada165(
datos,
3,
5
);
antSanJuan =
entrada165(
datos,
3,
6
);
antRojo =
entrada165(
datos,
3,
7
);
antSi =
entrada165(
datos,
4,
0
);
antNo =
entrada165(
datos,
4,
1
);
antMoneda1 =
entrada165(
datos,
4,
3
);
antMoneda2 =
entrada165(
datos,
4,
4
);
antMoneda5 =
entrada165(
datos,
4,
5
);
antMoneda10 =
entrada165(
datos,
4,
6
);
}
} else {
adminContando =
false;
}
vTaskDelay(
pdMS_TO_TICKS(30)
);
}
}