// DMX tester
// Aart 03-3026 
// 
//  - 4x20 lcd with PCF8574 on I2C 0x27. Arduino Pro Micro: SCL = 3, SDA  = 2
//  - RS485 receiver on Rx
//  - Potmeter 0-5V on A0
//
// Based on the DMXSerial library by Matthias Hertel, http://www.mathertel.de

const uint8_t BACKLIGHT = 10;  // Duration of backlight on in s. 

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#include <DMXSerial.h>

LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 16 chars and 2 line display

byte customBackslash[8] = {
  0b00000,
  0b10000,
  0b01000,
  0b00100,
  0b00010,
  0b00001,
  0b00000,
  0b00000
};

// number of DMX channels used
const int DMXLENGTH = 256;  

void setup()
{
  lcd.init();                      // initialize the lcd 
  lcd.createChar(7, customBackslash);
  // Print a message to the LCD.
  lcd.setBacklight(HIGH);
  lcd.setCursor(3,0);
  lcd.print("DMX tester 1.0");
  lcd.setCursor(4,1);
  lcd.print("Aart 03-2026");
  lcd.setCursor(6,2);
  lcd.print("");
  lcd.setCursor(7,3);

  DMXSerial.init(DMXProbe);
  DMXSerial.maxChannel(DMXLENGTH); // Aftert the channels, the onUpdate will be called when new data arrived.
  
  lcd.print("256 ch.");
  delay(1000); 
  lcd.clear(); 
}

void loop()
{ 
    static uint8_t indicator = 0;   
    static uint32_t lastActivity = millis(); 
    static int lastStartChannel = 0; 

    int startChannel = (analogRead(A0)>>4) * 4;
    
    // Backlight on/off  
    if (lastStartChannel != startChannel ) 
    {
      lastActivity = millis(); 
      lastStartChannel = startChannel; 
      WriteData(DMXSerial.getBuffer(), startChannel);
    }
    if ((millis() - lastActivity) > BACKLIGHT * 1000) lcd.setBacklight(LOW); else lcd.setBacklight(HIGH); 

    if (DMXSerial.receive()) 
    {
      WriteData(DMXSerial.getBuffer(), startChannel); 
      
      // Spinnning Receive Indicator 
      lcd.setCursor(19,3); 
      indicator++; if (indicator > 3) indicator = 0;   
      if (indicator == 0) lcd.print("-");
      if (indicator == 1) lcd.write(byte(7)); 
      if (indicator == 2) lcd.print("|");
      if (indicator == 3) lcd.print("/"); 
    }
}

void WriteData(uint8_t *ptr, int startChannel) {
  for (int i = 0; i < 4; i++ ) 
  {
    // Channel numbers 
    lcd.setCursor(0,i);
    printClear(i + startChannel);
    lcd.setCursor(10,i);
    printClear(i + 4 + startChannel);
    // Data
    lcd.setCursor(4,i);
    printClear(*(ptr + i + startChannel));
    lcd.setCursor(14,i);
    printClear(*(ptr + i + 4 + startChannel)); 
  }
}

void printClear(int value) // Write spaces after short numbers to avoid use of lcd.clear(); 
{ 
  lcd.print(value);
  if (value < 10) lcd.print(" "); 
  if (value < 100) lcd.print(" "); 
} 
