#include <Wire.h>
#include <Keypad.h>
#include <EEPROM.h>
#include <LiquidCrystal.h>
#define DEBUG_ENABLED
#define SLAVE_COUNT 16
#define PACKET_SIZE 12
#define CONFIG_SAVED 69
#ifdef DEBUG_ENABLED
#define DEBUG_PRINT(value) Serial.print(value)
#define DEBUG_PRINTLN(value) Serial.println(value)
#else
#define DEBUG_PRINT(value)
#define DEBUG_PRINTLN(value)
#endif
#define IP_MODE 0
#define MAC_MODE 1
#define UNIVERSE_MODE 2
#define SELECT_MODE 3
#define UPLOAD_MODE 4
uint8_t currentMode = IP_MODE;
#define ROWS 4
#define COLS 4
uint8_t colPins[COLS] = { 7, 6, 5, 4 };
uint8_t rowPins[ROWS] = { 11, 10, 9, 8 };
char keys[ROWS][COLS] = {
{ '1', '2', '3', 'A' },
{ '4', '5', '6', 'B' },
{ '7', '8', '9', 'C' },
{ 'F', '0', 'E', 'D' }
};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
#define MODE_CHANGE_PIN 2
#define CURSOR_MOVE_PIN 3
// LCD PINS
#define lcd_rs A3
#define lcd_enable A2
#define lcd_d4 A1
#define lcd_d5 A0
#define lcd_d6 13
#define lcd_d7 12
LiquidCrystal lcd(lcd_rs, lcd_enable, lcd_d4, lcd_d5, lcd_d6, lcd_d7);
uint8_t cursorX = 7;
uint8_t cursorY = 0;
char ip[SLAVE_COUNT][13];
char mc[SLAVE_COUNT][13];
char un[SLAVE_COUNT][6];
uint8_t packet[SLAVE_COUNT][PACKET_SIZE];
uint8_t currentArduino = 0;
unsigned long uploadStartTime = 0;
const unsigned long uploadDuration = 7000;
void setup() {
#ifdef DEBUG_ENABLED
Serial.begin(9600);
#endif
InitSettings();
InitLCD();
PrintUI();
}
void LoadConfig()
{
if (EEPROM.read(0) == CONFIG_SAVED)
{
for (int j = 0; j < SLAVE_COUNT; j++)
{
for (int i = 0; i < PACKET_SIZE; i++)
{
packet[j][i] = EEPROM.read((j * i) + 1);
}
}
EncodeData();
}
else
{
EEPROM.write(0, CONFIG_SAVED);
for (int j = 0; j < SLAVE_COUNT; j++)
{
for (int i = 0; i < PACKET_SIZE; i++)
{
EEPROM.write((j * i) + 1, random(0, 256));
}
}
LoadConfig();
}
}
void InitSettings()
{
LoadConfig();
Wire.begin();
pinMode(MODE_CHANGE_PIN, INPUT_PULLUP);
pinMode(CURSOR_MOVE_PIN, INPUT_PULLUP);
}
void UploadSettings()
{
for (int i = 0; i < SLAVE_COUNT; i++)
{
Wire.beginTransmission(i);
for (int j = 0; j < PACKET_SIZE; j++)
{
Wire.write(packet[i][j]);
DEBUG_PRINT("WRITING ");
DEBUG_PRINT(packet[i][j]);
DEBUG_PRINT(" TO DEVICE ");
DEBUG_PRINT(i);
DEBUG_PRINTLN();
}
Wire.endTransmission();
}
}
// From a packet to a char array
void EncodeData()
{
for (int i = 0 ; i < SLAVE_COUNT; i++)
{
sprintf(ip[i], "%03d%03d%03d%03d", packet[i][0], packet[i][1], packet[i][2], packet[i][3]);
sprintf(mc[i], "%02X%02X%02X%02X%02X%02X",
packet[i][4], packet[i][5], packet[i][6],
packet[i][7], packet[i][8], packet[i][9]);
int value = (packet[i][10] << 8) | packet[i][11];
sprintf(un[i], "%05d", value); // Convert uint16_t to string
}
}
// From char array to a packet
void PacketData()
{
}
void SaveSettings()
{
EEPROM.write(0, CONFIG_SAVED);
for (int i = 0; i < SLAVE_COUNT; i++)
{
for (int j = 0; j < PACKET_SIZE; j++)
{
EEPROM.write((i * j) + 1, packet[i][j]);
}
}
}
bool upload = false;
void PrintUI()
{
lcd.clear();
lcd.setCursor(0, 0);
char id[3];
sprintf(id, "%02d", currentArduino + 1);
lcd.print("ID: ");
lcd.print(id);
lcd.setCursor(0, 1);
lcd.print("MOD ");
if (currentMode == IP_MODE)
{
lcd.print("IP");
lcd.setCursor(7, 0);
lcd.print(ip[currentArduino][0]);
lcd.print(ip[currentArduino][1]);
lcd.print(ip[currentArduino][2]);
lcd.print('.');
lcd.print(ip[currentArduino][3]);
lcd.print(ip[currentArduino][4]);
lcd.print(ip[currentArduino][5]);
lcd.setCursor(7, 1);
lcd.print(ip[currentArduino][6]);
lcd.print(ip[currentArduino][7]);
lcd.print(ip[currentArduino][8]);
lcd.print('.');
lcd.print(ip[currentArduino][9]);
lcd.print(ip[currentArduino][10]);
lcd.print(ip[currentArduino][11]);
}
else if (currentMode == MAC_MODE)
{
lcd.print("MC");
lcd.setCursor(7, 0);
lcd.print(mc[currentArduino][0]);
lcd.print(mc[currentArduino][1]);
lcd.print(':');
lcd.print(mc[currentArduino][2]);
lcd.print(mc[currentArduino][3]);
lcd.print(':');
lcd.print(mc[currentArduino][4]);
lcd.print(mc[currentArduino][5]);
lcd.setCursor(7, 1);
lcd.print(mc[currentArduino][6]);
lcd.print(mc[currentArduino][7]);
lcd.print(':');
lcd.print(mc[currentArduino][8]);
lcd.print(mc[currentArduino][9]);
lcd.print(':');
lcd.print(mc[currentArduino][10]);
lcd.print(mc[currentArduino][11]);
}
else if (currentMode == UNIVERSE_MODE)
{
lcd.print("UN");
lcd.setCursor(7, 0);
lcd.print(un[currentArduino]);
}
else if (currentMode == SELECT_MODE)
{
lcd.print("SL");
}
lcd.setCursor(cursorX, cursorY);
DEBUG_PRINTLN("PRINTING UI");
}
void ProgressBar()
{
float progress = (millis() - uploadStartTime) / 1000.0;
lcd.setCursor(0, 0);
lcd.print(" SAVE CONFIG?");
if (progress < 0.5)
{
lcd.setCursor(1, 1);
lcd.print("*");
}
else if (progress > 0.5 && progress < 1)
{
lcd.setCursor(2, 1);
lcd.print("*");
}
else if (progress > 1 && progress < 1.5)
{
lcd.setCursor(3, 1);
lcd.print("*");
}
else if (progress > 1.5 && progress < 2)
{
lcd.setCursor(4, 1);
lcd.print("*");
}
else if (progress > 2 && progress < 2.5)
{
lcd.setCursor(5, 1);
lcd.print("*");
}
else if (progress > 2.5 && progress < 3)
{
lcd.setCursor(6, 1);
lcd.print("*");
}
else if (progress > 3 && progress < 3.5)
{
lcd.setCursor(7, 1);
lcd.print("*");
}
else if (progress > 3.5 && progress < 4)
{
lcd.setCursor(8, 1);
lcd.print("*");
}
else if (progress > 4 && progress < 4.5)
{
lcd.setCursor(9, 1);
lcd.print("*");
}
else if (progress > 4.5 && progress < 5)
{
lcd.setCursor(10, 1);
lcd.print("*");
}
else if (progress > 5 && progress < 5.5)
{
lcd.setCursor(11, 1);
lcd.print("*");
}
else if (progress > 5.5 && progress < 6)
{
lcd.setCursor(12, 1);
lcd.print("*");
}
else if (progress > 6 && progress < 6.5)
{
lcd.setCursor(13, 1);
lcd.print("*");
}
else if (progress > 6.5 && progress < 7)
{
lcd.setCursor(14, 1);
lcd.print("*");
}
}
void InitLCD()
{
lcd.begin(16, 2);
lcd.cursor();
}
void ResetCursor()
{
DEBUG_PRINTLN("RESETING CURSOR");
cursorX = 7;
cursorY = 0;
if (currentMode == SELECT_MODE || upload == true)
{
lcd.noCursor();
}
else
{
lcd.cursor();
}
PrintUI();
}
void MoveCursor(char c = '_')
{
if (upload)
{
return;
}
if (c != '_')
{
DEBUG_PRINT("Inserting character ");
DEBUG_PRINTLN(c);
}
DEBUG_PRINTLN("MOVING CURSOR");
DEBUG_PRINT("Before:\t");
DEBUG_PRINT("CursorX: ");
DEBUG_PRINT(cursorX);
DEBUG_PRINT("\tCursorY: ");
DEBUG_PRINT(cursorY);
DEBUG_PRINTLN();
if (currentMode == IP_MODE)
{
if (cursorX == 9)
{
cursorX += 2;
}
else if (cursorX == 13 && cursorY == 0)
{
cursorX = 7;
cursorY = 1;
}
else if (cursorX == 13 && cursorY == 1)
{
cursorX = 7;
cursorY = 0;
}
else
{
cursorX++;
}
}
else if (currentMode == MAC_MODE)
{
if (cursorX == 14 && cursorY == 0)
{
cursorX = 7;
cursorY = 1;
}
else if (cursorX == 8 || cursorX == 11)
{
cursorX += 2;
}
else if (cursorX == 14 && cursorY == 1)
{
ResetCursor();
}
else
{
cursorX++;
}
}
else if (currentMode == UNIVERSE_MODE)
{
if (cursorX == 11)
{
ResetCursor();
}
else
{
cursorX++;
}
}
DEBUG_PRINT("After:\t");
DEBUG_PRINT("CursorX: ");
DEBUG_PRINT(cursorX);
DEBUG_PRINT("\tCursorY: ");
DEBUG_PRINT(cursorY);
DEBUG_PRINTLN();
PrintUI();
}
void ChangeMode(bool up = false)
{
DEBUG_PRINTLN("CHANGING MODE");
currentMode++;
if (currentMode > 3)
{
currentMode = 0;
}
upload = up;
if (up)
{
lcd.clear();
currentMode = SELECT_MODE;
uploadStartTime = millis();
}
ResetCursor();
}
int lastButton = 0;
const int LONG_PRESS_uploadDuration = 1000;
unsigned long buttonPressuploadStartTime = 0;
bool isButtonPressed = false;
void ProcessButtons()
{
if (digitalRead(MODE_CHANGE_PIN) == LOW)
{
if (!isButtonPressed)
{
isButtonPressed = true;
buttonPressuploadStartTime = millis();
}
}
else if (digitalRead(CURSOR_MOVE_PIN) == HIGH && digitalRead(MODE_CHANGE_PIN) == HIGH && isButtonPressed)
{
isButtonPressed = false;
unsigned long pressuploadDuration = millis() - buttonPressuploadStartTime;
if (pressuploadDuration >= LONG_PRESS_uploadDuration)
{
if (upload)
{
upload = false;
ChangeMode();
return;
}
DEBUG_PRINTLN("Long press on MODE_CHANGE_PIN");
ChangeMode(true);
}
else
{
lastButton = MODE_CHANGE_PIN;
}
}
else if (digitalRead(CURSOR_MOVE_PIN) == LOW)
{
lastButton = CURSOR_MOVE_PIN;
}
else
{
if (lastButton == MODE_CHANGE_PIN)
{
DEBUG_PRINTLN("MODE_CHANGE_PIN pin");
ChangeMode();
}
else if (lastButton == CURSOR_MOVE_PIN)
{
DEBUG_PRINTLN("CURSOR_MOVE_PIN pin");
MoveCursor();
}
lastButton = 0;
}
}
void ProcessKeypad()
{
if (upload)
{
return;
}
char key = keypad.getKey();
if (key != NO_KEY) {
if (currentMode == SELECT_MODE)
{
if (key == 'A')
{
currentArduino++;
if (currentArduino >= SLAVE_COUNT)
{
currentArduino = 0;
}
}
else if (key == 'D')
{
currentArduino--;
if (currentArduino > SLAVE_COUNT)
{
currentArduino = SLAVE_COUNT - 1;
}
}
PrintUI();
}
else if (currentMode == MAC_MODE)
{
MoveCursor(key);
}
else if (key > 47 && key < 58)
{
MoveCursor(key);
}
}
}
void loop() {
ProcessButtons();
ProcessKeypad();
if (upload)
{
ProgressBar();
if (millis() - uploadStartTime >= uploadDuration)
{
PacketData();
SaveSettings();
UploadSettings();
ChangeMode();
}
}
}