How to make a digital clock using Arduino

Implementation of digital clock using Arduino, MAX7219 dot matrix display, DS1302 RTC real time clock, DHT11 humidity and temperature sensor and alarm active buzzer


Category: Arduino Tags: Arduino nano, MAX7219 4in1 Display, DHT11, DS1302 RTC, Active buzzer

Digital_Clock_Code_Files

    In this article we will learn how to make a digital clock using Arduino nano with below features:

  1. Display temperature & humidity
  2. Display date and day
  3. Can set alarm
  4. Can set time, day and date

Prerequisites:

  1. Arduino nano with cable
  2. DS1302 RTC
  3. MAX7219 4in1 Display
  4. DHT11 Temperature and Humidity sensor
  5. Active buzzer
  6. Momentary switches
  7. Two 220 ohm and one 10K ohm resistor
  8. Female to female jumper wires, normal wires
  9. 5v charger
  10. MDF board, paint, drill machine, screws, glue gun etc

Implementation

We will design our circuit based on below diagram. Momentary switches use 220ohm resistors and DHT sensor uses 10K ohm resistor.

 

Digital clock Circuit diagram with Arduino nano, RTC, DHT, MAX7219, Buzzer
Fig 1: Digital clock Circuit diagram


Two momentary switches are "back" and "select". On press back clock can display day, temperature, humidity etc. Select button works as menu which supports momentary press and long press. Momentary press is used to display menu items and long press is used to get into menu item also to save and exit.

If you want to change time, click on select button(button-2 in video) keep clicking until you see option "Time". Once time is displayed press and hold same button, you will be able to get into time setting mode. Click back(Button-1 in video) to change between hours and minutes, press select button to change time and again log press to save and exit.

Full video of making this clock:

Below is the code will be uploading to Arduino:

#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include "Font_Data.h"
#include <virtuabotixRTC.h>
#include "DHT.h"
#include <EEPROM.h>

//Display
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define DISPLAY_CLK_PIN   13
#define DISPLAY_DATA_PIN  11
#define DISPLAY_CS_PIN    10
//RTC
#define RTC_CLK_PIN  2
#define RTC_DATA_PIN  3
#define RTC_RST_PIN   4
//DHT
#define DHT_PIN 6
#define DHTTYPE DHT11

// Hardware SPI connection
MD_Parola P = MD_Parola(HARDWARE_TYPE, DISPLAY_CS_PIN, MAX_DEVICES);
//RTC
virtuabotixRTC myRTC(RTC_CLK_PIN,RTC_DATA_PIN,RTC_RST_PIN);
//DHT
DHT dht(DHT_PIN, DHTTYPE);

//OTHER PINS
#define BTN_BACK_PIN 8
#define BTN_SELECT_PIN 7
#define ALARM_PIN   5

char Buffer[7];

int SELECT = 0;
int SUBSELECT = 0;
int BACK = 0;
int OPTION = 0;
int RING = 0;
int ALARMHOUR = 6;
int ALARMMINUTE = 30;
int ALARMON = 0;
int ALARMOFFONBUTTONPRESS = 0;
int ROMALARMHOURADD = 0;
int ROMALARMMINUTEADD = 2;
int ROMALARMONADD = 4;

void setup(void)
{
  P.begin();
  dht.begin();
  Serial.begin(9600);
  P.setFont(newFont);
  P.setIntensity(1);
  
  pinMode(ALARM_PIN, OUTPUT);
  pinMode(BTN_BACK_PIN, INPUT);
  pinMode(BTN_SELECT_PIN, INPUT);

  ALARMHOUR=EEPROM.read(ROMALARMHOURADD);
  ALARMMINUTE=EEPROM.read(ROMALARMMINUTEADD);
  ALARMON=EEPROM.read(ROMALARMONADD);
  if(ALARMHOUR > 23) ALARMHOUR = 6;
  if(ALARMMINUTE > 59) ALARMHOUR = 30;
  if(ALARMON > 1) ALARMON = 0;
}

void loop(void)
{
  int alarmMinDiff = (myRTC.hours*60 + myRTC.minutes) - (ALARMHOUR*60 + ALARMMINUTE);
  //Ring if time is alarm time, alarm is on, user did not press any button and user is not inside menu
  if(alarmMinDiff == 0 && ALARMON == 1 && ALARMOFFONBUTTONPRESS == 0 && SELECT == 0)
  {
    ringAlarm();
  }
  else
  {
    digitalWrite(ALARM_PIN, LOW);
  }
  if(alarmMinDiff != 0)
  {
    ALARMOFFONBUTTONPRESS = 0;
  }
  
  int longPress = 0;
  if(digitalRead(BTN_BACK_PIN)==HIGH)
  {
    if(tryStopAlarm(alarmMinDiff) == 0)
      clickedBack();
  }

  while(digitalRead(BTN_SELECT_PIN)==HIGH)
  {
    longPress += 100;
    delay(100);
    if(longPress > 1500 || digitalRead(BTN_SELECT_PIN)==LOW)
      break;
      
    continue;
  }

  if(longPress > 0)
  {
    if(tryStopAlarm(alarmMinDiff) == 0)
    {
      if(SELECT > 0 && longPress > 1500)
      {
        clickedLongSelect();
      }
      else if(longPress > 0)
      {
        clickedSelect();
      }
    }
  }

  P.displayAnimate();

  while(digitalRead(BTN_BACK_PIN)==HIGH)
    delay(100);
  while(digitalRead(BTN_SELECT_PIN)==HIGH)
    delay(100);

  if(BACK == 0 && SELECT == 0)
  {
    displayTime();
  }
    
  delay(100);
}

void ringAlarm()
{
  if(RING == 0)
  {
    digitalWrite(ALARM_PIN, HIGH);
    RING = 1;
  }
  else
  {
    digitalWrite(ALARM_PIN, LOW);
    RING = 0;
  }
}

int tryStopAlarm(int alarmMinDiff)
{
  if(alarmMinDiff == 0 && ALARMON == 1 && ALARMOFFONBUTTONPRESS == 0)
  {
      ALARMOFFONBUTTONPRESS = 1;
      digitalWrite(ALARM_PIN, LOW);
      return 1;
  }
  return 0;
}
//---------------------------------Button click methods--------------------------------------//
void clickedBack()
{
  BACK++;
  if(SELECT == 0)
  {
    switch(BACK)
    {
      case 1:
        {
          displayDay();
          break;
        }
      case 2:
        {
          displayDate();
          break;
        }
      case 3:
        {
          displayTemparature();
          break;
        }
      case 4:
        {
          displayHumidity();
          break;
        }
      default:
        {
          BACK = 0;
          break;
        }
    }
  }
  else if(SELECT > 0)
  {
    switch(SUBSELECT)
    {
      case 1:
      {
        updateTime();
        break;
      }
      case 2:
      {
        updateDate();
        break;
      }
      case 3:
      {
        updateDay();
        break;
      }
      case 4:
      {
        updateAlarm();
        break;
      }
      case 5:
      {
        updateOnOffAlarm();
        break;
      }
      default:
      {
        reset();
      }
    }
  }
}

void clickedSelect()
{
  SELECT++;
  if(SUBSELECT == 0)
  {
    switch(SELECT)
    {
      case 1:
        {
          P.displayText("Time", PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
          break;
        }
      case 2:
        {
          P.displayText("Date", PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
          //P.displayText("Set Date", PA_LEFT, 60, 0, PA_SCROLL_LEFT, PA_NO_EFFECT);
          break;
        }
      case 3:
        {
          P.displayText("Day", PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
          break;
        }
      case 4:
        {
          P.displayText("Alarm", PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
          break;
        }
      case 5:
        {
          P.displayClear();
          P.displayText("ON/OFF - Alarm", PA_LEFT, 60, 0, PA_SCROLL_LEFT, PA_NO_EFFECT);
          break;
        }
      default:
        {
          SELECT = 0;
        }
    }
  }
  else
  {
    switch(SUBSELECT)
    {
      case 1:
      {
        if(OPTION == 0) OPTION++; else OPTION=0;
        displayOptionTime();
        break;
      }
      case 2:
      {
        if(OPTION < 2) OPTION++; else OPTION=0;
        displayOptionDate();
        break;
      }
      case 3:
      {
        displayOptionDay();
        break;
      }
      case 4:
      {
        if(OPTION == 0) OPTION++; else OPTION=0;
        displayOptionAlarm();
        break;
      }
      case 5:
      {
        displayOptionOnOffAlarm();
        break;
      }
      default:
      {
        SELECT = 0;
      }
    }
  }
}

void clickedLongSelect()
{
  if(SELECT > 0 && SUBSELECT > 0)
  {
    reset();
    displayTime();
  }
  if(SELECT > 0)
  {
    SUBSELECT = SELECT;
    switch(SELECT)
    {
      case 1:
        {
          displayOptionTime();
          break;
        }
      case 2:
        {
          displayOptionDate();
          break;
        }
      case 3:
        {
          displayOptionDay();
          break;
        }
      case 4:
        {
          displayOptionAlarm();
          break;
        }
      case 5:
        {
          displayOptionOnOffAlarm();
          break;
        }
    }
  }
}
//---------------------------------Update Date Time--------------------------------------//
void updateTime()
{
  if(OPTION == 0)
  {
    int hours = myRTC.hours < 23 ? myRTC.hours + 1 : 0;
    myRTC.setDS1302Time(00, myRTC.minutes, hours, myRTC.dayofweek, myRTC.dayofmonth, myRTC.month, myRTC.year);
  }
  else
  {
    int minutes = myRTC.minutes < 59 ? myRTC.minutes + 1 : 0;
    myRTC.setDS1302Time(00, minutes, myRTC.hours, myRTC.dayofweek, myRTC.dayofmonth, myRTC.month, myRTC.year);
  }
  myRTC.updateTime();
  displayOptionTime();
}

void updateDate()
{
  if(OPTION == 0)
  {
    int dayofmonth = myRTC.dayofmonth < 31 ? myRTC.dayofmonth + 1 : 1;
    myRTC.setDS1302Time(00, myRTC.minutes, myRTC.hours, myRTC.dayofweek, dayofmonth, myRTC.month, myRTC.year);
  }
  else if(OPTION == 1)
  {
    int month = myRTC.month < 12 ? myRTC.month + 1 : 1;
    myRTC.setDS1302Time(00, myRTC.minutes, myRTC.hours, myRTC.dayofweek, myRTC.dayofmonth, month, myRTC.year);
  }
  else if (OPTION == 2)
  {
    int year = myRTC.year < 2050 ? myRTC.year + 1 : 2020;
    myRTC.setDS1302Time(00, myRTC.minutes, myRTC.hours, myRTC.dayofweek, myRTC.dayofmonth, myRTC.month, year);
  }
  myRTC.updateTime();
  displayOptionDate();
}
void updateDay()
{
  int dayofweek = myRTC.dayofweek < 7 ? myRTC.dayofweek + 1 : 1;
  myRTC.setDS1302Time(00, myRTC.minutes, myRTC.hours, dayofweek, myRTC.dayofmonth, myRTC.month, myRTC.year);
  myRTC.updateTime();
  displayOptionDay();
}
void updateAlarm()
{
  if(OPTION == 0)
  {
    ALARMHOUR = ALARMHOUR < 23 ? ALARMHOUR + 1 : 0;
    EEPROM.write(ROMALARMHOURADD, ALARMHOUR);
  }
  else
  {
    ALARMMINUTE = ALARMMINUTE < 59 ? ALARMMINUTE + 1 : 0;
    EEPROM.write(ROMALARMMINUTEADD, ALARMMINUTE);
  }
  displayOptionAlarm();
}
void updateOnOffAlarm()
{
  if(ALARMON == 0) ALARMON++; else ALARMON = 0;
  EEPROM.write(ROMALARMONADD, ALARMON);
  displayOptionOnOffAlarm();
}
//---------------------------------Display methods--------------------------------------//
void displayTime()
{
  myRTC.updateTime();
  int hours = myRTC.hours > 12 ? myRTC.hours - 12 : myRTC.hours == 0 ? 12 : myRTC.hours;
  sprintf(Buffer,"%02d : %02d",hours,myRTC.minutes);
  P.displayText(Buffer, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
}

void displayTemparature()
{
  int tempC = dht.readTemperature();
  sprintf(Buffer,"%02d ºC", tempC);
  P.displayText(Buffer, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
}

void displayHumidity()
{
  int humi  = dht.readHumidity();
  sprintf(Buffer,"%02d %%", humi);
  P.displayText(Buffer, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
}

void displayDay()
{
  myRTC.updateTime();
  char* dayPtr = getDay(myRTC.dayofweek);
  P.displayText(dayPtr, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
}

void displayDate()
{
  myRTC.updateTime();
  char* monthPtr = getMonth(myRTC.month);
  sprintf(Buffer,"%s %02d", monthPtr, myRTC.dayofmonth);
  P.displayText(Buffer, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
}

void displayOptionTime()
{ 
  if(OPTION == 0)
    sprintf(Buffer,">%02d:%02d",myRTC.hours,myRTC.minutes);
  else
    sprintf(Buffer,"%02d:>%02d",myRTC.hours,myRTC.minutes);
    
  P.displayText(Buffer, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
}

void displayOptionDate()
{
  if(OPTION == 0)
    sprintf(Buffer,"D>%02d",myRTC.dayofmonth);
  else if(OPTION == 1)
    sprintf(Buffer,"M>%02d",myRTC.month);
  else
    sprintf(Buffer,"Y>%02d",myRTC.year);
    
  P.displayText(Buffer, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
}
void displayOptionDay()
{
  char* dayName = getDay(myRTC.dayofweek);
  sprintf(Buffer,"D>%0s",dayName);
  P.displayText(Buffer, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
}
void displayOptionAlarm()
{ 
  if(OPTION == 0)
    sprintf(Buffer,">%02d:%02d",ALARMHOUR,ALARMMINUTE);
  else
    sprintf(Buffer,"%02d:>%02d",ALARMHOUR,ALARMMINUTE);
    
  P.displayText(Buffer, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
}
void displayOptionOnOffAlarm()
{ 
  if(ALARMON == 0)
    P.displayText("> OFF", PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
  else
    P.displayText("> ON", PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
}
//-------------------------------Day/month int to string methods----------------------------------//
char* getDay(int dayofweek)
{
  switch(dayofweek)
  {
    case 1:
      return "MON";
    case 2:
      return "TUE";
    case 3:
      return "WED";
    case 4:
      return "THU";
    case 5:
      return "FRI";
    case 6:
      return "SAT";
    case 7:
      return "SUN";
  }
}

char* getMonth(int monthNo)
{
  switch(monthNo)
  {
    case 1:
      return "JAN";
    case 2:
      return "FEB";
    case 3:
      return "MAR";
    case 4:
      return "APR";
    case 5:
      return "MAY";
    case 6:
      return "JUN";
    case 7:
      return "JUL";
    case 8:
      return "AUG";
    case 9:
      return "SEP";
    case 10:
      return "OCT";
    case 11:
      return "NOV";
    case 12:
      return "DEC";
  }
}

void reset()
{
  SELECT = 0;
  BACK = 0;
  SUBSELECT = 0;
  OPTION = 0;
}

 

Font_Data.h file also to be added to Arduino code:

// Data file for user example user defined fonts
#ifndef FONTDATA_H
#define FONTDATA_H

MD_MAX72XX::fontType_t newFont[] PROGMEM = 
{
  0,  // 0  
  0,  // 1  
  0,  // 2  
  0,  // 3  
  0,  // 4  
  0,  // 5  
  0,  // 6  
  0,  // 7  
  0,  // 8  
  0,  // 9  
  0,  // 10  
  0,  // 11  
  0,  // 12  
  0,  // 13  
  0,  // 14  
  0,  // 15  
  0,  // 16  
  0,  // 17  
  0,  // 18  
  0,  // 19  
  0,  // 20  
  0,  // 21  
  0,  // 22  
  0,  // 23  
  0,  // 24  
  0,  // 25  
  0,  // 26  
  0,  // 27  
  0,  // 28  
  0,  // 29  
  0,  // 30  
  0,  // 31  
  1, 0,   // 32  
  0,  // 33  
  0,  // 34  
  0,  // 35  
  0,  // 36  
  5, 152, 88, 32, 208, 200,   // 37  
  0,  // 38  
  0,  // 39  
  0,  // 40  
  0,  // 41  
  0,  // 42  
  0,  // 43  
  0,  // 44  
  0,  // 45  
  0,  // 46  
  5, 64, 32, 16, 8, 4,  // 47  
  5, 124, 162, 146, 138, 124,   // 48  
  5, 136, 132, 254, 128, 128,   // 49  
  5, 132, 194, 162, 146, 140,   // 50  
  5, 68, 146, 146, 146, 108,  // 51  
  5, 48, 40, 36, 254, 32,   // 52  
  5, 78, 138, 138, 138, 114,  // 53  
  5, 124, 146, 146, 146, 100,   // 54  
  5, 2, 226, 18, 10, 6,   // 55  
  5, 108, 146, 146, 146, 108,   // 56  
  5, 76, 146, 146, 146, 124,  // 57  
  1, 40,  // 58  
  0,  // 59  
  0,  // 60  
  0,  // 61  
  3, 68, 40, 16,   // 62    
  0,  // 63  
  0,  // 64  
  5, 252, 18, 18, 18, 252,  // 65  
  5, 254, 146, 146, 146, 108,   // 66  
  5, 124, 130, 130, 130, 68,  // 67  
  5, 254, 130, 130, 130, 124,   // 68  
  5, 254, 146, 146, 146, 130,   // 69  
  5, 254, 18, 18, 18, 2,  // 70  
  5, 124, 130, 130, 162, 100,   // 71  
  5, 254, 16, 16, 16, 254,  // 72  
  3, 130, 254, 130,   // 73  
  5, 64, 130, 130, 130, 126,  // 74  
  5, 254, 16, 16, 40, 198,  // 75  
  5, 254, 128, 128, 128, 128,   // 76  
  5, 254, 4, 8, 4, 254,   // 77  
  5, 254, 8, 16, 32, 254,   // 78  
  5, 124, 130, 130, 130, 124,   // 79  
  5, 254, 18, 18, 18, 12,   // 80  
  5, 124, 130, 162, 194, 252,   // 81  
  5, 254, 18, 18, 18, 236,  // 82  
  5, 76, 146, 146, 146, 100,  // 83  
  5, 2, 2, 254, 2, 2,   // 84  
  5, 126, 128, 128, 128, 126,   // 85  
  5, 62, 64, 128, 64, 62,   // 86  
  5, 254, 64, 32, 64, 254,  // 87  
  5, 198, 40, 16, 40, 198,  // 88  
  5, 6, 8, 240, 8, 6,   // 89  
  5, 194, 162, 146, 138, 134,   // 90  
  8, 0, 0, 0, 0, 0, 0, 0, 0,  // 91  
  0,  // 92  
  0,  // 93  
  0,  // 94  
  0,  // 95  
  0,  // 96  
  5, 64, 168, 168, 168, 248,  // 97  
  5, 254, 144, 136, 136, 112,   // 98  
  5, 112, 136, 136, 136, 64,  // 99  
  5, 112, 136, 136, 144, 254,   // 100  
  5, 112, 168, 168, 168, 48,  // 101  
  4, 16, 252, 18, 2,  // 102  
  5, 16, 168, 168, 168, 120,  // 103  
  5, 254, 16, 8, 8, 240,  // 104  
  3, 136, 250, 128,   // 105  
  3, 128, 136, 122,   // 106  
  4, 254, 32, 80, 136,  // 107  
  3, 130, 254, 128,   // 108  
  5, 248, 8, 240, 8, 240,   // 109  
  5, 248, 8, 8, 8, 240,   // 110  
  5, 112, 136, 136, 136, 112,   // 111  
  5, 248, 40, 40, 40, 16,   // 112  
  5, 16, 40, 40, 40, 248,   // 113  
  5, 248, 16, 8, 8, 16,   // 114  
  5, 144, 168, 168, 168, 72,  // 115  
  5, 4, 254, 132, 128, 64,  // 116  
  5, 120, 128, 128, 128, 248,   // 117  
  5, 24, 96, 128, 96, 24,   // 118  
  5, 120, 128, 96, 128, 120,  // 119  
  5, 136, 72, 112, 144, 136,  // 120  
  5, 136, 144, 96, 32, 24,  // 121  
  5, 136, 200, 168, 152, 136,   // 122  
  0,  // 123  
  0,  // 124  
  0,  // 125  
  0,  // 126  
  0,  // 127  
  0,  // 128  
  0,  // 129  
  0,  // 130  
  0,  // 131  
  0,  // 132  
  0,  // 133  
  0,  // 134  
  0,  // 135  
  0,  // 136  
  0,  // 137  
  0,  // 138  
  0,  // 139  
  0,  // 140  
  0,  // 141  
  0,  // 142  
  0,  // 143  
  0,  // 144  
  0,  // 145  
  0,  // 146  
  0,  // 147  
  0,  // 148  
  0,  // 149  
  0,  // 150  
  0,  // 151  
  0,  // 152  
  0,  // 153  
  0,  // 154  
  0,  // 155  
  0,  // 156  
  0,  // 157  
  0,  // 158  
  0,  // 159  
  0,  // 160  
  0,  // 161  
  0,  // 162  
  0,  // 163  
  0,  // 164  
  0,  // 165  
  0,  // 166  
  0,  // 167  
  0,  // 168  
  0,  // 169  
  0,  // 170  
  0,  // 171  
  0,  // 172  
  0,  // 173  
  0,  // 174  
  0,  // 175  
  0,  // 176  
  0,  // 177  
  0,  // 178  
  0,  // 179  
  0,  // 180  
  0,  // 181  
  0,  // 182  
  0,  // 183  
  0,  // 184  
  0,  // 185  
  4, 12, 18, 18, 12,  // 186  
  0,  // 187  
  0,  // 188  
  0,  // 189  
  0,  // 190  
  0,  // 191  
  0,  // 192  
  0,  // 193  
  0,  // 194  
  0,  // 195  
  0,  // 196  
  0,  // 197  
  0,  // 198  
  0,  // 199  
  0,  // 200  
  0,  // 201  
  0,  // 202  
  0,  // 203  
  0,  // 204  
  0,  // 205  
  0,  // 206  
  0,  // 207  
  0,  // 208  
  0,  // 209  
  0,  // 210  
  0,  // 211  
  0,  // 212  
  0,  // 213  
  0,  // 214  
  0,  // 215  
  0,  // 216  
  0,  // 217  
  0,  // 218  
  0,  // 219  
  0,  // 220  
  0,  // 221  
  0,  // 222  
  0,  // 223  
  0,  // 224  
  0,  // 225  
  0,  // 226  
  0,  // 227  
  0,  // 228  
  0,  // 229  
  0,  // 230  
  0,  // 231  
  0,  // 232  
  0,  // 233  
  0,  // 234  
  0,  // 235  
  0,  // 236  
  0,  // 237  
  0,  // 238  
  0,  // 239  
  0,  // 240  
  0,  // 241  
  0,  // 242  
  0,  // 243  
  0,  // 244  
  0,  // 245  
  0,  // 246  
  0,  // 247  
  0,  // 248  
  0,  // 249  
  0,  // 250  
  0,  // 251  
  0,  // 252  
  0,  // 253 
  0,  // 254 
  0,  // 255
};
#endif

 


Like 0 People
Last modified about 9 days ago
Nikhil Joshi

Nikhil Joshi
Ceo & Founder at Dotnetlovers
Atricles: 139
Questions: 12
Given Best Solutions: 12 *

Reference:


Comments:

No Comments Yet

You are not loggedin, please login or signup to add comments:

Existing User

Login via:

New User



x