Alarm Clock Radio

 

To program the ATmega328, download and install the Arduino Software. Connect the clock to a USB port on your PC and copy the sketch below (Arduino's name for a 'program') and upload it.

Setting the Clock's Features

Setting the Time & Date

  • Set the Radio-off-Alarm switch to 'Off'.
  • Press the 'Set' button for 1 second, then release. The display will show:
      Set Clock...
         Hours:  12
    
  • Use the Up and Down buttons to set the Hours. Then press ok/next. The display will show:
      Set Clock...
         Mins:  45
    
  • Use the Up and Down to set the minutes. Then press ok/next.
  • Set Seconds, Day, Date, Month and Year in the same way.
  • Pressing ok/next after setting the Year will return the clock to the normal display.

Setting the Alarm

  • Set the Radio-off-Alarm switch to 'Alarm'.
  • Set the Hours and Minutes in the same way as above.
  • Pressing ok/next after setting the Minutes will return the clock to the normal display.

Advanced Settings

  • Set the Radio-off-Alarm switch to 'Radio'.
  • Press the 'Set' button for 1 second, then release. The display will show:
      Sleep in 20 mins
    
  • Set the 'sleep' timer with the Up and Down buttons, then press ok/next.
  • the display will show:
      Snooze for 20 mins
    
  • Set the 'snooze' timer with the Up and Down buttons, then press ok/next.
  • the display will show:
       Exit?  Y
    
  • To finish setting and return to the normal display, press ok/next.
  • To move on to more advance settings, press Up or Down. The display will show:
       Exit?  N
    
  • Press ok/next and the display will show:
      LCD Min: 50
    
  • The LCD backlight will adjust according to the ambient light and this shows the minimum brightness you'll see at night. Use the Up and Down buttons to adjust. then hit ok/next.
  •   LCD Level:  550/750
    
  • The first number is the light level at which the display begins to darken. The second figure is the current light level.
  • use Up and Down to adjust, then hit ok/next.
      Local Osc: High
    
  • Press Down to change to 'Low' and Up to change back to 'High.' Changing this setting might be useful in eliminating strong interference to a radio channel.
  • Press ok/next to return to the normal display.

Sleep at night

With the Radio-Off-Alarm switch set to either 'Off' or 'Alarm', press the ok/next button to play the radio for 'Sleep' time.
Cancel the sleep time by pressing the ok/next button again.

Snooze in the morning

When the Alarm sounds, press the ok/next button to silence the alarm for 'Snooze' time. Repeat indefinitely.


The Arduino Sketch

Note: The code for the LCD is for an old serial backback that is no longer available. To help you convert the code to match the LCD you will be using, this page explains what the codes I've used actually do.

// Bedside Alarm Clock Radio (c) vwlowen.co.uk

#include <SoftwareSerial.h>
#include <SPI.h>
#include <Wire.h>
#include <EEPROM.h>

unsigned char frequencyH = 0;
unsigned char frequencyL = 0;

unsigned int frequencyB;
double frequency = 0;


#define rxPin 0
#define txPin 2
#define lcdBacklight 3
#define okNextButton 4
#define radioON 5            //  3-position switch: Radio - off - Alarm
#define alarmON 6            //
#define setButton  7
#define upButton 8
#define downButton 9

#define chipEnablePin  10    // RTC Enable

#define alarmOUT A0          // Digital Output for piezo buzzer
#define ampPower A1          // Digital Output to Power Audio Amp DC volume control 

int readVolume = A2;         // Determines radio volume or external buzzer
int ldrInput  = A3;          // Measure ambient light to set LCD backlight brightness.



// set up a new serial port for the ByVac serial LCD. 
SoftwareSerial lcd(rxPin, txPin);
 
// Set up meaningful arrays for day and month names for the LCD. 

char* daynames[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
char* monthnames[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
                        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
                        
// Custom LCD characters for a 'bell' & 'hourglass' symbols and large digits segments.                        
 
byte bell[8] = {0, 4, 14, 14, 14, 31, 4, 0};
byte hourglass[8] = {31, 17, 10, 4, 14, 31, 31, 0};
byte radio[8] = {0, 4, 6, 5, 5, 4, 28, 28};

byte segments[5][8] = {
{ B11111,B11111,B00000,B00000,B00000,B00000,B00000,B00000 },
{ B00000,B00000,B00000,B00000,B00000,B00000,B11111,B11111 },
{ B11111,B11111,B00000,B00000,B00000,B00000,B11111,B11111 },
{ B11111,B11111,B11111,B11111,B11111,B11111,B11111,B11111 } ,
{ B00000,B00000,B00000,B00000,B00000,B01110,B01110,B01110 } };

const int digitWidth = 3; // the width in characters of a big digit

const char bigDigitsTop[10][digitWidth]={
                3,0,3, 0,3,32, 2,2,3, 0,2,3, 3,1,3, 3,2,2, 3,2,2, 0,0,3, 3,2,3, 3,2,3};
const char bigDigitsBot[10][ digitWidth]={
           //     3,1,3, 1,3,1, 3,1,1, 1,1,3, 32,32,3, 1,1,3, 3,1,3, 32,32,3, 3,1,3, 1,1,3};
            3,1,3, 1,3,1, 3,1,1, 1,1,3, 32,32,3, 1,1,3, 3,1,3, 32,3,32, 3,1,3, 1,1,3};
                
char buffer[12]; // used to convert a number into a string

byte hours;
byte minutes;
byte seconds;
byte day;
byte date;
byte month;
byte year;

byte hoursAlarm;
byte minutesAlarm;

//EEPROM locations for items to save during power out.

byte savedHours = 0;           // Alarm time.
byte savedMinutes = 1;

byte savedRadioChannel = 2;

byte savedlcdMin = 3;                   
byte savedlcdThreshold = 4;         
byte savedHighSideLO = 6;
byte savedSleepMins = 7;
byte savedSnoozeMins = 8;
boolean alarmTriggered = false;

byte highSideLO;

float fmFreq[10] = {98.5, 89.3, 91.5, 93.7, 95.8, 96.7, 97.1, 97.4, 100.4, 101.1};
char* fmName[10] = {"Radio 1 ", "Radio 2 ", "Radio 3 ", "Radio 4 ", "Mersey  ",
                      "City FM ", "Buzz    ", "Rock FM ", "Smooth  ", "Classic "};
                      
int currentChannel = 9;  
unsigned long tim;
unsigned long sleepTim;
int sleepMins;                   // Time for sleep and snooze functions (mins)...
unsigned long sleepDelay;        // ... and expressed as milliseconds.
int snoozeMins;
unsigned long snoozeDelay;

int lcdMin = 1;                  // Minimum LCD backlight brightness
int lcdThreshold = 400;          // Threshold for dimming backlight


boolean radioState = false;
boolean sleepRadio = false;
boolean snooze = false;

void setup() {
  delay(1500);  // Allow LCD time to power up properly.
  
  // Get radio channel, LCD brightness settings and sleep & snooze timers from EEPROM
  // Set sensible defaults if EEPROM hasn't been set yet.
  
  currentChannel = EEPROM.read(savedRadioChannel);
  if ((currentChannel < 0) || (currentChannel > 9)) currentChannel = 0;
  frequency = fmFreq[currentChannel];   

  lcdMin = EEPROM.read(savedlcdMin);
  lcdThreshold = EEPROMReadInt(savedlcdThreshold);  
  
  sleepMins = EEPROM.read(savedSleepMins);
  if (sleepMins > 30) sleepMins = 30;
  sleepDelay = sleepMins * 60000;
  
  snoozeMins = EEPROM.read(savedSnoozeMins);
  if (snoozeMins > 30) snoozeMins = 30;
  snoozeDelay = snoozeMins * 60000;  
  
  // Initialize I2C for radio chip
  Wire.begin();

  lcd.begin(19200);                              // Initialize the ByVac Serial LCD.
  lcd.print("\r");
  lcd.print("\r");
  delay(100);

  lcd.print("ac1\r");                            // Clear display  
  lcd.print("acc\r");                            // Cursor Off
  delay(10);
  
  // Set ATmega328 inputs and outputs
 
  pinMode(chipEnablePin, OUTPUT);                // Set the RTC Chip Enable pin as output.
  pinMode(alarmOUT, OUTPUT);
  pinMode(lcdBacklight, OUTPUT);
  pinMode(ampPower, OUTPUT);                     // 5v to audio amp. volume to allow muting.
  
  pinMode(setButton, INPUT);                       // Set the Time-Set switch as an inpit.
  pinMode(okNextButton, INPUT);                  // OK/NEXT
  pinMode(upButton, INPUT);                      // UP
  pinMode(downButton, INPUT);                    // Down
  pinMode(radioON, INPUT);
  pinMode(alarmON, INPUT);
  
  digitalWrite(chipEnablePin, LOW);
  SPI.begin();                                   //  Set up the SPI library for clock.
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE1);   
  
   // Initialize RTC Control Register.
  writeRegister(0x8f, B00000000);                // bit 2 set = 1Hz (pin 7) OFF; 
  
  
  createCustom(5, bell);
  createCustom(6, hourglass);
  createCustom(7, radio);
  
  for(int i=0; i < 5; i++)
    createCustom(i, segments[i]);                // create the 5 custom segments
    
  lcd.print("ac1\r");                            // Clear display    
  delay(100);
  rowcol(1,9);                                   // Print large ':' between hrs and mins
  lcdWrite(0xa5);
  rowcol(2,9);
  lcdWrite(0xa5);  
  
  // Determine if Radio Local Oscillator should be High or Low side.
  
  highSideLO = EEPROM.read(savedHighSideLO);
  if ((highSideLO != 0xB0) && (highSideLO != 0xA0)) {
    highSideLO = 0xB0;
  }   

  setFrequency();

}


void loop() {
  
 // Set LCD backlight according to LDR measurement.
  analogWrite(lcdBacklight, 
               constrain(map(analogRead(ldrInput), 20, lcdThreshold,  lcdMin, 255), lcdMin, 255));
  
 
  if ((digitalRead(radioON) == HIGH) ||  (digitalRead(alarmON) == HIGH) || sleepRadio){
    if (digitalRead(upButton) == HIGH)   checkUpButton();
    if (digitalRead(downButton) == HIGH)   checkDownButton();
  }


  if (digitalRead(setButton) == HIGH) {    // Check if set-clock sbutton is pressed.
    delay(1000);
    if (digitalRead(setButton) == HIGH) {
      if (digitalRead(alarmON) == HIGH) setAlarm();
      if (digitalRead(radioON) == HIGH) AdvancedSettings();
      if ((digitalRead(alarmON) == LOW) && (digitalRead(radioON) == LOW))  setClock();
    }
  }
  
 // Show 'bell' symbol if alarm is set to ON.
  if (digitalRead(alarmON) == HIGH) {
    rowcol(1, 0);
    lcdWrite(5);
  } else {
    alarmTriggered = false;
  }
  
 // Show 'radio' symbol if radio is set to ON.  
  if (digitalRead(radioON) == HIGH) {
    rowcol(1, 0);
    lcdWrite(7);
  } 

  if ((digitalRead(alarmON) == LOW) && (digitalRead(radioON) == LOW)){
    rowcol(1, 0);
    lcdWrite(0x20);    
  }  
  
  
  // read clock time and date registers.  
  seconds = bcd2dec(readRegister(0x00), B1111); 
  minutes = bcd2dec(readRegister(0x01), B1111);
  hours = bcd2dec(readRegister(0x02), B11);
  
  day = readRegister(0x03) & B111;         // Day register is only bits 0, 1 and 2 
  date = bcd2dec(readRegister(0x04), B11);
  month = bcd2dec(readRegister(0x05), B11);
  year = bcd2dec(readRegister(0x06), B1111);
  
  
  // Display 'large digits' for hours & minutes.

  if (hours > 9) {
    showNumber(hours, 0);
  } else {
    showDigit(0, 0);
    showNumber(hours, 1);
  }

  if (minutes > 9) {
    showNumber(minutes, 2);
  } else {
    showDigit(0, 2);
    showDigit(minutes, 3);
  }
  
  // Display seconds at 'normal' LCD digit size

  rowcol(2, 18);
  if (seconds < 10) {
    lcd.print("ad0\r");
  }
  lcdPrint(seconds);
  
  // Display Day and Date.

  rowcol(4, 2);
  lcd.print("ad");                                
  lcd.print(daynames[day - 1]);
  lcd.print(" \r");

  if (date < 10) {
    lcd.print("ad0\r");
  }
  lcdPrint(date);

  lcd.print("ad ");
  lcd.print(monthnames[month-1]);                  // Print month name on LCD.
  lcd.print(" \r");
  
  lcd.print("ad20\r");
  lcdPrint(year);
  delay(10);
  
  
  
 // When radio is On, press ok/Next for station info
  if ((digitalRead(radioON) == HIGH) && (digitalRead(okNextButton) == HIGH)) {
    showChannel();
  }
  
  // Set up all the flags that can turn the radio on or off.
  
  // Turn on Radio ON manually
  if ((digitalRead(radioON) == HIGH)  && !radioState) {
      radioState = true;
      sleepRadio = false;
      rowcol(2, 0);
      lcdWrite(0x20);  
      showChannel();
      delay(50);
   }
   
   
   if ((digitalRead(radioON) == LOW) && !sleepRadio && !alarmTriggered) {
     radioState = false;
     sleepRadio = false;
   }
   
 
   // Turn Radio ON with 'Sleep' button (okNextButton)
   if (  (digitalRead(radioON) == LOW)  && !alarmTriggered && !sleepRadio  &&
       (digitalRead(okNextButton) == HIGH)) {

       sleepRadio = true;
       radioState = false;
       rowcol(2, 0);
       lcdWrite(6);
 
       showChannel(); 
       sleepTim = millis();
       while (digitalRead(okNextButton) == HIGH);
       delay(100);
   }
   
 
   // Cancel 'Sleep' funtion with timer or manually (by pressing ok/next button again)
   if (((millis() > (sleepTim + sleepDelay)) || (digitalRead(okNextButton) == HIGH))  && sleepRadio) {
      sleepRadio = false;
      rowcol(2, 0);
      lcdWrite(0x20);              
      while (digitalRead(okNextButton) == HIGH);
      delay(100);
    }
   
   // Allow Snooze when alarm is triggered
   if (alarmTriggered && (digitalRead(alarmON) == HIGH)  && (digitalRead(okNextButton) == HIGH)) {
       snooze = true;
      rowcol(2, 0);
      lcd.print("adz\r");              
       sleepTim = millis();
       while (digitalRead(okNextButton) == HIGH);
       delay(100);
   }  
   
   // End snooze time to allow alarm to sound again if alarmTriggered is still active.
   if (millis() > (sleepTim + snoozeDelay)  && snooze) {
     snooze = false;
      rowcol(2, 0);
      lcdWrite(0x20);                 
   }
   
  // Get alarm hours and mins from EEPROM. check for validity.
   minutesAlarm = EEPROM.read(savedMinutes);
   if ((minutesAlarm < 0) || (minutesAlarm > 59)) minutesAlarm = 0;
   hoursAlarm = EEPROM.read(savedHours);
   if ((hoursAlarm < 0) || (hoursAlarm > 23)) hoursAlarm = 0; 
  
  
   if ( (hours == hoursAlarm) && (minutes == minutesAlarm) && 
          (seconds >= 0) && (seconds < 2) && (digitalRead(alarmON) == HIGH) && 
          !alarmTriggered) {
       alarmTriggered = true;
   } 
  

   if ( (sleepRadio || radioState || (alarmTriggered && !snooze))) {
      digitalWrite(ampPower, HIGH);
      delay(50);
     
     // Turn on Buzzer if volume setting is too low.
     if ((analogRead(readVolume) < 140) && alarmTriggered ){
         digitalWrite(alarmOUT, HIGH);
     } else {
         digitalWrite(alarmOUT, LOW);
     }       
    } else {
       digitalWrite(ampPower, LOW); 
       digitalWrite(alarmOUT, LOW);
    }   
}

void showChannel() {
      digitalWrite(ampPower, HIGH);
      if (digitalRead(radioON) == HIGH) {
        rowcol(1,0);
        lcdWrite(7);
      }
      rowcol(4,2);
      lcd.print("ad");
      lcd.print(fmName[currentChannel]);
      lcd.print("        \r");
      delay(800);
      tim = millis();
      while ( (millis() - tim < 5000) && 
                   (digitalRead(downButton) == LOW) && (digitalRead(upButton) == LOW)  ) {
                     
        seconds = bcd2dec(readRegister(0x00), B1111);
        rowcol(2, 18);
        if (seconds < 10) {
          lcd.print("ad0\r");
        }
        lcdPrint(seconds);
      
        if ((digitalRead(okNextButton) == HIGH)  && sleepRadio) {
          sleepRadio = false;
          rowcol(2,0);
          lcdWrite(0x20);
          delay(250);
          return;
        }        
        
        if ((digitalRead(radioON) == LOW) && !sleepRadio){
          radioState = false;
          return;
        }
      }    
}


void setFrequency()
{
   if (highSideLO == 0xB0) {
    frequencyB = 4 * (frequency * 1000000 + 225000) / 32768;
  } else {
    frequencyB = 4 * (frequency * 1000000 - 225000) / 32768;
  }
  frequencyH = frequencyB >> 8;
  frequencyL = frequencyB & 0XFF;
//  delay(100);
  Wire.beginTransmission(0x60);
  
  Wire.write(frequencyH);  
  Wire.write(frequencyL);
  Wire.write(highSideLO);
  Wire.write(B00011010);  // 32kHz xtal, soft mute, stereo noise reduction
  Wire.write((byte)0x00);


  Wire.endTransmission();
  delay(50); 
}

void checkUpButton() {
  int oldChannel = currentChannel;
  if (digitalRead(upButton) == HIGH) {
    while (digitalRead(upButton) == HIGH) {
      currentChannel++;
      if (currentChannel > 9) currentChannel = 0;
      frequency = fmFreq[currentChannel];     
      setFrequency();
      showChannel();
    }
  }
  if (currentChannel != oldChannel) {
    EEPROM.write(savedRadioChannel, currentChannel);
  }
}

void checkDownButton() {
  int oldChannel = currentChannel;
  if (digitalRead(downButton) == HIGH) {
    while (digitalRead(downButton) == HIGH) {
      currentChannel--;
      if (currentChannel < 0) currentChannel = 9;
      frequency = fmFreq[currentChannel];     
      setFrequency();
      showChannel();
    }
  }  
  if (currentChannel != oldChannel) {
    EEPROM.write(savedRadioChannel, currentChannel);
  }
}

void AdvancedSettings() {
  rowcol(4, 0);
  lcd.print("adSleep in ");
  lcd.print(sleepMins);
  lcd.print(" mins     \r");
  
  while(digitalRead(okNextButton) == LOW) {  //  OK/NEXT not pressed
     if (digitalRead(upButton) == HIGH) {
        sleepMins = sleepMins + 5;
        if (sleepMins > 30 ) sleepMins = 5;
     } 
     if (digitalRead(downButton) == HIGH) {
        sleepMins = sleepMins - 5;
        if (sleepMins < 5) sleepMins = 30;
     }
     rowcol(4, 9);
     lcdPrint(sleepMins);
     delay(500);
  }
  EEPROM.write(savedSleepMins, sleepMins);
  sleepDelay = sleepMins * 60000;
  while(digitalRead(okNextButton) == HIGH); 
  
  rowcol(4, 0);
  lcd.print("adSnooze for ");
  lcd.print(snoozeMins);
  lcd.print("  mins\r");
  
  while(digitalRead(okNextButton) == LOW) {  //  OK/NEXT not pressed
     if (digitalRead(upButton) == HIGH) {
        snoozeMins = snoozeMins + 5;
        if (snoozeMins > 30 ) snoozeMins = 5;
     } 
     if (digitalRead(downButton) == HIGH) {
        snoozeMins = snoozeMins - 5;
        if (snoozeMins < 5) snoozeMins = 30;
     }
     rowcol(4, 11);
     lcdPrint(snoozeMins);
     delay(500);
  }
  EEPROM.write(savedSnoozeMins, snoozeMins);
  snoozeDelay = snoozeMins * 60000;
  while(digitalRead(okNextButton) == HIGH);     
  
  
  char p = 'Y';
  
  rowcol(4, 0);
  lcd.print("adExit? ");
  lcd.print(p);
  lcd.print("           \r");
  
  while(digitalRead(okNextButton) == LOW) {  //  OK/NEXT not pressed
     if ((digitalRead(upButton) == HIGH) || (digitalRead(downButton) == HIGH)) {
       if (p == 'Y') {
         p = 'N';
       } else {
         p = 'Y';
      }  
     }
     while ((digitalRead(upButton) == HIGH) || (digitalRead(downButton) == HIGH));
       rowcol(4, 6);
       lcd.print("ad");
       lcd.print(p);
       lcd.print("\r");
  }
  if (p == 'Y') {
    rowcol(4, 0);
    lcd.print("ad                \r");
    return;
  }

  while(digitalRead(okNextButton) == HIGH); 
  
  rowcol(4, 0);
  lcd.print("adLCD Min: ");
  lcd.print(lcdMin);
  lcd.print("        \r");
  
  
  while(digitalRead(okNextButton) == LOW) {  //  OK/NEXT not pressed
     if (digitalRead(upButton) == HIGH) {
        lcdMin++;
        if (lcdMin > 200 ) lcdMin = 1;
     } 
     if (digitalRead(downButton) == HIGH) {
        lcdMin--;
        if (lcdMin < 1) lcdMin = 200;
     }
     analogWrite(lcdBacklight, lcdMin);
     rowcol(4, 0);
     lcd.print("adLCD Min: ");
     lcd.print(lcdMin);
     lcd.print("        \r");
     delay(250);
  }
  while(digitalRead(okNextButton) == HIGH);
    
  rowcol(4, 0);
  lcd.print("adLCD Level: ");
  lcd.print(lcdThreshold);
  lcd.print("      \r");
  
  
  while(digitalRead(okNextButton) == LOW) {  //  OK/NEXT not pressed
    if (digitalRead(upButton) == HIGH) {
        lcdThreshold = lcdThreshold + 5;
        if (lcdThreshold > 700 ) lcdThreshold = 100;
    } 
    if (digitalRead(downButton) == HIGH) {
       lcdThreshold  = lcdThreshold - 5;
       if (lcdThreshold < 100) lcdThreshold = 700;
    }
    int temp;
    int light = analogRead(ldrInput);
 
    temp = constrain(map(light, 20, lcdThreshold,  lcdMin, 255), lcdMin, 255);

    analogWrite(lcdBacklight,temp );
    rowcol(4, 0);
    lcd.print("adLCD Level: ");
    lcd.print(lcdThreshold);
    lcd.print("/");
    lcd.print(light);
    lcd.print("  \r");
    delay(250);
   }
     while(digitalRead(okNextButton) == HIGH);
    
     rowcol(4, 0);
     lcd.print("adLoc Osc: ");
     if (highSideLO == 0xB) lcd.print("High");
     if (highSideLO == 0xA0) lcd.print("Low");
     lcd.print("      \r");
      
    
    while(digitalRead(okNextButton) == LOW) {  //  OK/NEXT not pressed
      if (digitalRead(upButton) == HIGH) {
        highSideLO = 0xB0;
        
      } 
      if (digitalRead(downButton) == HIGH) {
        highSideLO = 0xA0;
      }    
     rowcol(4, 0);
     lcd.print("adLoc Osc: ");
     if (highSideLO == 0xB0) lcd.print("High");
     if (highSideLO == 0xA0) lcd.print("Low");
     lcd.print("      \r");
    }    

    EEPROM.write(savedlcdMin, lcdMin); 
    EEPROMWriteInt(savedlcdThreshold, lcdThreshold);
    EEPROM.write(savedHighSideLO, highSideLO);
    setFrequency();
    while (digitalRead(setButton) == HIGH);     
    lcd.print("ac1\r");

}

void EEPROMWriteInt(int p_address, int p_value) {
   byte lowByte = ((p_value >> 0) & 0xFF);
   byte highByte = ((p_value >> 8) & 0xFF);

   EEPROM.write(p_address, lowByte);
   EEPROM.write(p_address + 1, highByte);
  }

unsigned int EEPROMReadInt(int p_address) {
    byte lowByte = EEPROM.read(p_address);
    byte highByte = EEPROM.read(p_address + 1);
    return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
}



void lcdPrint(byte value) {                     // Function to print value on LCD
  lcd.print("ad");
  lcd.print(value);
  lcd.print(" \r");
}

void lcdWrite(byte value) {
  lcd.print("ad");
  lcd.write(value);
  lcd.print(" \r");
}

byte readRegister(byte Reg) {
  digitalWrite(chipEnablePin, HIGH);
  SPI.transfer(Reg);
  byte getByte = SPI.transfer(Reg);
  digitalWrite(chipEnablePin, LOW);
  return getByte;
}

void writeRegister(byte Reg, byte value) {
  digitalWrite(chipEnablePin, HIGH);
  SPI.transfer(Reg);
  SPI.transfer(value);  
  digitalWrite(chipEnablePin, LOW);  
}

byte bcd2dec(byte value, byte mask) {
  byte units = value & B00001111;           
  byte tens = ((value >> 4) & mask) * 10;     
                                            
  return  tens + units;                    
} 

byte dec2bcd(byte value, byte mask) {
  byte bcdHigh = ((value / 10) << 4) & mask; 
                                             
  byte bcdLow = value % 10;                  
  return bcdHigh | bcdLow;              
}


void setAlarm() {
  lcd.print("ac1\r");
  lcd.print("adSet Alarm...\r");
  hoursAlarm = EEPROM.read(savedHours);
  minutesAlarm = EEPROM.read(savedMinutes);
  updateAlarm("Hours: ", hoursAlarm, savedHours, 23, 0);
  updateAlarm("Mins:  ", minutesAlarm, savedMinutes, 59, 0);  
  while (digitalRead(setButton) == HIGH);
  lcd.print("ac1\r"); 
  rowcol(1,9);
  lcdWrite(0xa5);
  rowcol(2,9);
  lcdWrite(0xa5);  
}


void setClock() {
  lcd.print("ac1\r");
  lcd.print("adSet Clock...\r");
  updateClock("Hours: ", hours, 0x82, B00110000, 23, 0);
  updateClock("Mins:  ", minutes, 0x81, B11110000, 59, 0);
  updateClock("Secs: ", seconds, 0x80, B11110000, 59, 0);
  updateClock("Day:   ", day, 0x83, B0, 7, 1);
  updateClock("Date:  ", date, 0x84, B00110000, 31, 1);
  updateClock("Month: ", month, 0x85, B00110000, 12, 1);
  updateClock("Year: ", year, 0x86, B11110000, 70, 12);
  while (digitalRead(setButton) == HIGH);
  lcd.print("ac1\r");
  rowcol(1,9);
  lcdWrite(0xa5);
  rowcol(2,9);
  lcdWrite(0xa5);  
}


void updateAlarm(char* prompt, byte item,  byte addr, byte maximum, byte minimum) {
  if (digitalRead(okNextButton) == HIGH) return;
    rowcol(3, 4);
    lcd.print("ad");
    lcd.print(prompt);
    lcd.print("  \r");

    rowcol(3, 12);
    if (item < 10) lcd.print("ad0\r");
    lcdPrint(item);
    
    while(digitalRead(okNextButton) == LOW) {  //  OK/NEXT not pressed
      if (digitalRead(upButton) == HIGH) {
        item++;
        if (item > maximum) item = minimum;
      } 
      if (digitalRead(downButton) == HIGH) {
        item--;
        if (item < minimum) item = maximum;
        if (item > maximum) item = maximum;
      }
      rowcol(3, 12);   
      if (item < 10) lcd.print("ad0\r");
      lcdPrint(item);
      lcd.print("ad  \r");
      delay(500);
    }
    
    EEPROM.write(addr, item); 
    while (digitalRead(okNextButton) == HIGH);   
}

void updateClock(char* prompt, byte item, byte reg, byte mask, byte maximum, byte minimum) {
   if (digitalRead(okNextButton) == HIGH) return;
    rowcol(3, 4);
    lcd.print("ad");
    lcd.print(prompt);
    lcd.print("  \r");

    rowcol(3, 12);
    
    if (maximum == 70) {
      rowcol(3,10);
      lcd.print("ad20\r");
    }
    if (maximum == 12) {
      lcd.print("ad");                               
      lcd.print(monthnames[item - 1]);
      lcd.print("   \r");
    }     
    if (maximum == 7) {
      lcd.print("ad");                               
      lcd.print(daynames[item - 1]);
      lcd.print("   \r");
    }

    if ((maximum != 7) && (maximum != 12)) {
      if (item < 10) lcd.print("ad0\r");
      lcdPrint(item);
    }

    while(digitalRead(okNextButton) == LOW) {  //  OK/NEXT not pressed
      if (digitalRead(upButton) == HIGH) {
        item++;
        if (item > maximum) item = minimum;
      } 
      if (digitalRead(downButton) == HIGH) {
        item--;
        if (item < minimum) item = maximum;
        if (item > maximum) item = maximum;
      }
      rowcol(3, 12);
        
      if (maximum == 12) {
        lcd.print("ad");                               
        lcd.print(monthnames[item - 1]);
        lcd.print("   \r");
      }             
        
      if (maximum == 7) {
        lcd.print("ad");                               
        lcd.print(daynames[item - 1]);
        lcd.print("\r");
      } 

      if ((maximum != 7) && (maximum != 12)) {
         if (item < 10) lcd.print("ad0\r");
        lcdPrint(item);
      }
        lcd.print("ad  \r");
        delay(500);
      }
    
    int val = dec2bcd(item, mask);
    writeRegister(reg, val);    
    while (digitalRead(okNextButton) == HIGH);
    
}

void showDigit(int digit, int position) {
  rowcol(1, (position * (digitWidth + 1)) + 2);
  for(int i=0; i < digitWidth; i++) {
    lcd.print("ad");
    lcd.write(bigDigitsTop[digit][i]);
    lcd.print("\r");
  }
  rowcol(2, (position * (digitWidth + 1)) + 2);
  for(int i=0; i < digitWidth; i++) {
    lcd.print("ad");
    lcd.write(bigDigitsBot[digit][i]);
    lcd.print("\r");
  }
}

void showNumber(int value, int position) {
  int index; // index to the digit being printed, 0 is the leftmost digit
  itoa(value, buffer, 10); // see Recipe 2.8 for more on using itoa
// display each digit in sequence
  for(index = 0; index < 10; index++) {
    char c = buffer[index];
    if( c == 0) // check for null (not the same as '0')
       return; // the end of string character is a null, see Chapter 2
    c = c - 48; // convert ascii value to a numeric value (see Recipe 2.9)
    showDigit(c, position + index);
  }
}


void rowcol(char row, char col) {
    char b[5];
    int r;
    lcd.print("ac");
    switch(row) {
        case 1: { r = 0x80; break; }
        case 2: { r = 0xc0; break; }
        case 3: { r = 0x94; break; }
        case 4: { r = 0xd4; break; }
        default: { r = 0x80; break; }
    }
    int rc = r + col;
    itoa(rc, b, 16);
    lcd.print(b);
    lcd.print("\r");

}


void createCustom(char chrnum, byte cgramData[]) {
    char b[5];
    int loc;  
  
    lcd.print("ac");                      // Send the device address to the LCD. (default is 'a')
   
    switch(chrnum) {                      // Enumerate the LCD CGRAM location
       case 0: { loc = 0x40; break; }     
       case 1: { loc = 0x48; break; }
       case 2: { loc = 0x50; break; }
       case 3: { loc = 0x58; break; }
       case 4: { loc = 0x60; break; }
       case 5: { loc = 0x68; break; }
       case 6: { loc = 0x70; break; }
       case 7: { loc = 0x78; break; }
       default: { loc = 0x40; break;}
     } 
     itoa(loc, b, 16);
     lcd.print(b);
     lcd.print("\r");                            // Terminate the input with CR.

     delay(100);
           
     lcd.print("ad");                             // Tell the LCD that data is coming ('d').
                
     for(char i=0; i<8; i++)                     // Write the contents of the previously-created array
       lcd.write(cgramData[i]);                  // to the GCRAM location.
     lcd.print("\r");
     delay(300);

                       // Reset the LCD memory to the normal display DDRAM.
     lcd.print("ac80\r");
     delay(50); 
}



 

Back to Index | Page 1 | Page 2 | Page 3 | Page 4 | Page 5

 


This site and its contents are © Copyright 2005 - All Rights Reserved.