Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <avr/interrupt.h>
- #include <avr/io.h>
- #include <stdlib.h>
- #include <\\puffball.labs.eait.uq.edu.au\s4264101\Documents\i2cmaster.h>
- //#include <C:\Users\battlemage\Downloads\twimaster.c>
- //#include <C:\Users\battlemage\Downloads\i2cmaster.h>
- #define DS1307 0b11010000
- #define ENABLE 32
- #define TIME_BTN 77
- #define SETTING_BTN 83
- #define ENTER_BTN 81
- #define DATE_BTN 69
- #define ALARM_BTN 85
- #define NEXT_BTN 67
- #define PREV_BTN 75
- #define WEATHER_SET 3
- #define WEATHER_BTN 73
- void update_time(void); //Updates Time Variables from RTC
- void set_rtc_time(void); //Sends time to RTC
- char dec2bcd(char); //Converts numbers from Decimal to Binary-coded Decimal
- char bcd2dec(char); //Converts numbers from Binary-coded Decimal to Decimal
- void configure_display(void); //Chooses what to show on the display
- void update_display(int); //Adds a given integer into the display array
- void add_display(int); //Adds a specific led into the display array
- void cycle_leds(void); //Cycles through the display array
- void add_current_alarm(void); //Adds the last alarm recieved to alarm array
- void check_for_alarm(); //Checks the alarm array for alarms at current time
- void clear_leds(void); //Clears the ledsOn array
- void update_time_variables(void); //Updates time global variables
- void reset_clock(void); //Resets the global time variables
- char get_command(void); //Calculates the decimal value of the last infrared command recieved
- void deal_with_command(void); //Directs the program after recieving an IR command
- void enter_button_pressed(void); //Directs the program after recieving a "Set" IR command
- void prev_button_pressed(void); //Updates the display when "Previous" button is pressed
- void next_button_pressed(void); //Updates the display when "Next" button is pressed
- void set_time(void); //Controls IR time setting
- void set_date(void); //Controls IR date setting
- void set_alarm(void); //Controls IR alarm setting
- void setting_mode(void); //Controls IR setting mode
- void check_clock(void); //Checks to see if Optical "clock" has changed
- void read_data(void); //Reads data off the Optical "data" pin
- char get_adc(void); //Calculates decimal value of last optical command
- void deal_with_adc(void); //Directs program after recieving an optical command
- void clear_adc(void); //Clears the optical command array
- void adc_setting_mode(void); //Controls Optical Setting mode
- void adc_set(void); //Directs program while in Optical setting
- void adc_weather_set(void); //Controlls Optical weather Setting
- void adc_set_time(void); //Controls Optical time setting
- void adc_set_alarm(void); //Controls Optical alarm setting
- void adc_set_date(void); //Controls Optical date setting
- int ledDemux[17] = {12, 24, 28, 0, 2, 4, 6, 16, 20, 18, 22, 14, 10, 8, 26, 30, 12}; //Demux values for LEDs
- volatile int ledsOn[8] = {-1, -1, -1, -1, -1, -1, -1, -1}; //Current Leds on Display
- volatile int irArray[8] = {-1, -1, -1, -1, -1, -1, -1, -1}; //IR commands recieved
- volatile int adcArray[8] = {-1, -1, -1, -1, -1, -1, -1, -1}; //Optical commands recieved
- volatile int oldSeconds = 0; //Previously checked seconds
- volatile int prevOldSeconds = 0; //Prviously checked seconds
- volatile int lastCycle = 0; //Last LED turned on
- volatile int irCount = 0; //Number of bits in current IR signal recieved
- volatile int change = 0; //DONT THINK WE NEED -------------------------------------------------------------
- volatile int display = 0; //Display enabled -- 0 == enabled
- volatile int newSignal = 0; //Ready for new signal -- 0 == ready
- volatile int wavesMissed = 0; //Number of IR reads missed to avoid repetition of commands
- volatile int displayMode = 0; //Current Display -- 0 = time, 1 = date, 2 = weather
- volatile int dateDisplayChange = 0; //Time when display was changed to date
- volatile int weatherDisplayChange = 0; //Time when display was changed to weather
- volatile int weatherType = 0; //Current weather -- 1 = fine, 2 = rain, 3 = cloud
- volatile int oldADC = 0; //Previous Optical clock
- volatile int currentADC = 0; //Current Optical clock
- volatile int adcCount = 0; //Number of bits in current Optical command
- volatile int adcDelay = -1; //Pause between optical reads
- volatile int lastTimeCheck = -1; //Delays time between RTC communication
- //Time Variables
- volatile int seconds = 0; //Number of seconds in current minute
- volatile int minutes = 0; //Number of minutes in current hour
- volatile int hours = 0; //Number of hours in current day
- volatile int day = 1; //Number of days in current month
- volatile int month = 1; //Number of months in current year
- volatile int year = 2012; //Current year
- volatile int ampm = 0; //Current am/pm
- volatile int changeSeconds = -1; //Number of seconds in current minute
- volatile int changeMinutes = -1; //Number of minutes in current hour
- volatile int changeHours = -1; //Number of hours in current day
- volatile int changeDay = -1; //Number of days in current month
- volatile int changeMonth = -1; //Number of months in current year
- volatile int changeYear = -1; //Current year
- volatile int changeAmpm = -1; //Current am/pm
- //Alarm Variables
- int alarmNow = 0; //Alarm needs to trigger
- int buzzPrev = 0; //Last Buzzer Check
- int buzzCount = 0; //Number of seconds remaining on buzzer
- int adcNum = 0; //Second last Optical command
- int settingMode = 0; //In IR setting mode
- int adcSettingMode = 0; //In Optical Setting mode
- int currentLedIndex = 0; //Current Led turned on in setting mode
- int specificSet = 0; //If a specific setting mode has been selected (time, alarm etc.)
- int alarms[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; //Alarms Set
- int alarmMeridians[10] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,}; //Corresponding am/pm for alarms
- // Time Setting
- int timeSetting = 0;
- int minutesSet = 0;
- int hoursSet = 0;
- int tempMeridian = 0;
- //Optical temp variables
- int adcHours = 0;
- int adcMinutes = 0;
- int adcAmpm = 0;
- int adcCommandStart = -1; //Time when optical command begins to be recieved
- int adcSettingStart = -1; //Time when optical setting mode is enabled
- int weatherSetting = 0; // Weather Setting
- // Alarm Setting
- int dateSetting = 0;
- int minuteResoSet = 0;
- int alarmSetting = 0;
- int tempMinutes = 0;
- int tempHours = 0;
- int tempAmPm = 0;
- // Date Setting
- int tempLeap = 0;
- int yearSet = 0;
- int yearResoSet = 0;
- int monthSet = 0;
- int daySet = 0;
- int dayResoSet = 0;
- int adcYear = 0;
- int adcMonth = 0;
- int adcDay = 0;
- /* Main loop for clock processing*/
- int main(void) {
- DDRB = 0xFF; //Basic I/O Setup
- PORTB = 0x00;
- DDRB = 0x3F;
- DDRC = 0xFF;
- PORTC = 0x00;
- DDRC = 0x32;
- DDRD = 0xFF;
- PORTD = 0x00;
- DDRD = 0xC0;
- sei(); //Global Interrupts on
- EICRA |= (1 << ISC00); // set INT0 to trigger on ANY logic change
- EIMSK |= (1 << INT0); // Turns on INT0
- TIMSK1 |= (1 << OCIE1A); // Enable CTC interrupt
- TCCR1B |= (1 << WGM12); // Configure timer 1 for CTC mode
- OCR1A = 840; // Trigger every 0.84ms
- TCCR1B |= ((1 << CS10)); // Start timer at Fcpu/1
- TIMSK0 |= (1 << OCIE0A); // Enable CTC interrupt
- TCCR0A |= (1 << WGM01); // Configure timer 1 for CTC mode
- OCR0A = 80;
- TCCR0B |= ((1 << CS01));
- ADMUX = 0x40; //ADC Setup for ADC0
- ADCSRA = 0x86; //Configure ADC to run on demand
- ADCSRB = 0x00;
- ADCSRA |= 0x40; //Run initial ADC check
- while ((ADCSRA & 0x40) != 0x00); //Wait for check to finish
- check_clock(); //Check initial ADC
- for (int i = 0; i < 8; i++) { //Clear array resulting from check
- adcArray[i] = -1;
- }
- i2c_init(); //Initialise I2C communication for RTC
- changeSeconds = 0;
- changeMinutes = 0;
- changeHours = 0;changeAmpm = 0;
- set_rtc_time();
- while(1) {
- /* Setting mode while loop if in setting mode */
- if(settingMode) {
- PORTD &= 0xBF;
- setting_mode(); //Setting mode while loop
- }
- //Optical taken too long to receive a command
- if ((adcCommandStart != -1) && (seconds == ((adcCommandStart + 5) % 60))) {
- clear_adc();
- adcCommandStart = -1;
- }
- //Check the Optical Sensors
- if (((ADCSRA & 0x40) == 0) && (adcDelay == -1)) { //NEW
- ADCSRA |= 0x40;
- while ((ADCSRA & 0x40) != 0x00); //Wait for conversion to finish
- check_clock();
- }
- /* Setting mode for ADC, GUI data transfer */
- if(adcSettingMode) {
- adc_setting_mode();
- }
- //ALARM CHECK
- check_for_alarm();
- //If alarm is found
- if(alarmNow) {
- PORTC |= 0b00000010; //Turn on buzzer
- if(buzzPrev != seconds) { //Decrement the buzzer timer (buzzCount)
- buzzPrev = seconds;
- buzzCount--;
- }
- if(buzzCount == 0) { //If the buzzer doesn't need to be sounded anymore, turn it off
- PORTC &= 0b11111101;
- alarmNow = 0;
- buzzCount = 0;
- buzzPrev = 0;
- }
- }
- //DISPLAY
- if (lastTimeCheck == -1) {
- update_time(); //Update time from RTC
- configure_display(); //configure what is displayed
- update_time_variables(); //Update global time variables
- lastTimeCheck = 0;
- }
- }
- }
- //Used for IR communication. Started after IR command begins
- ISR(TIMER1_COMPA_vect) {
- if (lastTimeCheck != -1) {
- lastTimeCheck++;
- if (lastTimeCheck == 200) {
- lastTimeCheck = -1;
- }
- }
- /* Read in IR value */
- if (newSignal == 1) {
- if(!display) { //Not in displaymode
- if((PIND & 0x04) == 0x04) { //Read data
- irArray[irCount] = 1;
- } else {
- irArray[irCount] = 0;
- }
- irCount++; //Another bit read
- OCR1A = 1680; //Read in a full waves time
- if (irCount == 8) { //If full IR signal recieved
- change = 0;
- irCount = 0; //reset IR counter
- display = 1; //enable display again
- if(settingMode) { //If already in settingmode
- deal_with_command(); //Act on command
- } else if (get_command() == SETTING_BTN) { //Otherwise if command was set
- if(!adcSettingMode) { //If its not already setting Optical
- settingMode = 1; //Enter IR setting mode
- }
- } else if (get_command() == DATE_BTN) { //If command is date
- dateDisplayChange = seconds; //Start the date display
- displayMode = 1;
- } else if (get_command() == WEATHER_BTN) { //If command is weather
- weatherDisplayChange = seconds; //Start weather display
- displayMode = 2;
- }
- EIMSK |= (1 << INT0); // Turns on INT0
- }
- } else { //Otherwise skip IR reads to avoid second signal
- wavesMissed++; //Increment waves missed
- if (wavesMissed == 65) { //If enough waves missed
- //TCCR1B |= (0 << CS10); //Able to recieve new command
- //TIMSK1 = 0;
- wavesMissed = 0;
- newSignal = 0;
- display = 0;
- }
- }
- }
- }
- //Timer for cycling display and tracking ADC delays
- ISR(TIMER0_COMPA_vect) {
- if((settingMode == 0) && (adcSettingMode == 0)) { //If not setting
- cycle_leds(); //Cycle through LED array
- }
- if (adcDelay != -1) { //If waiting for next Optical read
- adcDelay++; //Increment delay to 700
- if (adcDelay == 700) {
- adcDelay = -1;
- }
- }
- }
- //Infrared reciever pin change
- ISR(INT0_vect) {
- if (newSignal == 0) { //Ready to get new signal
- EIMSK |= (0 << INT0); // Turns off INT0_vect
- change = 1;
- TCNT1 = 0; //clears timer register
- OCR1A = 840; //Sets timer to read HALF an ir wave from now!! IMPORTANT
- TCCR1B |= ((1 << CS10)); // Start timer at Fcpu/1
- TIMSK1 |= (1 << OCIE1A);
- newSignal = 1;
- }
- }
- //Gets the current seconds value form RTC
- void update_time(void) {
- i2c_start_wait(DS1307+I2C_WRITE); // set device address and write mode
- i2c_write(0x00); // write address = =0
- i2c_rep_start(DS1307+I2C_READ); // set device address and read mode
- seconds = i2c_readAck(); // read one byte
- seconds = bcd2dec(seconds); //Convert from Binary Coded Decimal
- minutes = i2c_readAck();
- minutes = bcd2dec(minutes);
- hours = i2c_readNak();
- hours = bcd2dec(hours);
- if (hours >= 12) {
- hours -= 12;
- ampm = 1;
- } else {
- ampm = 0;
- }
- i2c_stop();
- }
- //set_rtc_time sets the time for given global variables; changeSeconds, changeMinutes etc.
- void set_rtc_time(void) {
- //Wait for RTC to be ready to be written to
- i2c_start_wait(DS1307+I2C_WRITE);
- i2c_write(0x00);
- //Write seconds to RTC
- if (changeSeconds != -1) {
- i2c_write(dec2bcd(changeSeconds));
- } else {
- i2c_write(dec2bcd(seconds));
- }
- //Write minutes to RTC
- if (changeMinutes != -1) {
- i2c_write(dec2bcd(changeMinutes));
- } else {
- i2c_write(dec2bcd(minutes));
- }
- //Write hours to RTC
- if (changeHours != -1) {
- if (changeAmpm == 1) {
- i2c_write(dec2bcd(changeHours + 12));
- } else {
- i2c_write(dec2bcd(changeHours));
- }
- //Write according to ampm (plus 12 hours if pm)
- } else {
- if (ampm == 1) {
- i2c_write(dec2bcd(hours + 12));
- } else {
- i2c_write(dec2bcd(hours));
- }
- }
- //Finish writing and reset all global variables
- i2c_stop();
- changeSeconds = -1;
- changeMinutes = -1;
- changeHours = -1;
- changeAmpm = -1;
- }
- //Add the minutes to the display correctly
- void update_display(int time) {
- int outer = time / 5;
- int inner = time % 5;
- for (int i = 0; i < 8; i++) { //Clear array
- ledsOn[i] = -1;
- }
- //Assign values to ledsOn to be displayed based on 'outer' and 'inner'
- ledsOn[0] = ledDemux[outer];
- if (inner != 0) {
- for (int i = 0; i < inner; i++) {
- ledsOn[i+1] = ledDemux[i+12];
- }
- }
- }
- //Runs the display.
- //displayMode 0 is time
- //displayMode 1 is date
- //displayMode 2 is weather
- void configure_display(void) {
- if (displayMode == 0) {
- if ((seconds % 2) == 0) { //flash the hours in time mode
- update_display(minutes);
- add_display(hours);
- } else {
- update_display(minutes);
- }
- if (ampm == 1) { //turn on am/pm light if its pm
- PORTD |= 0x40;
- } else {
- PORTD &= 0xBF;
- }
- } else if (displayMode == 1) { //date
- if (seconds < ((dateDisplayChange + 3) % 60)) {
- update_display(day); //Show the day and bottom of 3 middle LEDs
- PORTB |= 0x01;
- PORTD &= 0x3F;
- } else if (seconds < ((dateDisplayChange + 6) % 60)) {
- if (month != 12) { //Show the month
- update_display(month*5);
- } else {
- update_display(0);
- }
- //show 2nd bottom of 3 middle LEDs
- PORTB &= 0xFE;
- PORTD &= 0x3F;
- PORTD |= 0x80;
- } else if (seconds < ((dateDisplayChange + 9) % 60)) {
- update_display(year - 2000); //Show the year and top of 3 middle LEDs
- PORTD &= 0x3F;
- PORTD |= 0x40;
- } else {
- dateDisplayChange = 0;
- PORTD &= 0x3F;
- displayMode = 0;
- }
- } else if (displayMode == 2) { //Weather
- if (weatherType == 0) { //Fine
- //Display method for weather below:
- if (seconds < ((weatherDisplayChange + 1) % 60)) {
- clear_leds();
- add_display(6);
- } else if (seconds < ((weatherDisplayChange + 2) % 60)) {
- clear_leds();
- add_display(7);
- add_display(5);
- } else if (seconds < ((weatherDisplayChange + 3) % 60)) {
- clear_leds();
- add_display(8);
- add_display(4);
- } else if (seconds < ((weatherDisplayChange + 4) % 60)) {
- clear_leds();
- add_display(9);
- add_display(3);
- } else if (seconds < ((weatherDisplayChange + 5) % 60)) {
- clear_leds();
- add_display(6);
- } else if (seconds < ((weatherDisplayChange + 6) % 60)) {
- clear_leds();
- add_display(7);
- add_display(5);
- } else if (seconds < ((weatherDisplayChange + 7) % 60)) {
- clear_leds();
- add_display(8);
- add_display(4);
- } else if (seconds < ((weatherDisplayChange + 8) % 60)) {
- clear_leds();
- add_display(9);
- add_display(3);
- } else {
- weatherDisplayChange = 0;
- displayMode = 0;
- }
- } else if (weatherType == 1) { //Rainy
- if (seconds < ((weatherDisplayChange + 1) % 60)) {
- clear_leds();
- add_display(0);
- } else if (seconds < ((weatherDisplayChange + 2) % 60)) {
- clear_leds();
- add_display(1);
- add_display(11);
- } else if (seconds < ((weatherDisplayChange + 3) % 60)) {
- clear_leds();
- add_display(2);
- add_display(10);
- } else if (seconds < ((weatherDisplayChange + 4) % 60)) {
- clear_leds();
- add_display(9);
- add_display(3);
- } else if (seconds < ((weatherDisplayChange + 5) % 60)) {
- clear_leds();
- add_display(0);
- } else if (seconds < ((weatherDisplayChange + 6) % 60)) {
- clear_leds();
- add_display(1);
- add_display(11);
- } else if (seconds < ((weatherDisplayChange + 7) % 60)) {
- clear_leds();
- add_display(2);
- add_display(10);
- } else if (seconds < ((weatherDisplayChange + 8) % 60)) {
- clear_leds();
- add_display(9);
- add_display(3);
- } else {
- weatherDisplayChange = 0;
- displayMode = 0;
- }
- } else if (weatherType == 2) { //Cloudy
- if (seconds < ((weatherDisplayChange + 1) % 60)) {
- clear_leds();
- add_display(3);
- add_display(9);
- } else if (seconds < ((weatherDisplayChange + 2) % 60)) {
- clear_leds();
- add_display(8);
- add_display(2);
- } else if (seconds < ((weatherDisplayChange + 3) % 60)) {
- clear_leds();
- add_display(7);
- add_display(1);
- } else if (seconds < ((weatherDisplayChange + 4) % 60)) {
- clear_leds();
- add_display(6);
- add_display(0);
- } else if (seconds < ((weatherDisplayChange + 5) % 60)) {
- clear_leds();
- add_display(11);
- add_display(5);
- } else if (seconds < ((weatherDisplayChange + 6) % 60)) {
- clear_leds();
- add_display(10);
- add_display(4);
- } else if (seconds < ((weatherDisplayChange + 7) % 60)) {
- clear_leds();
- add_display(9);
- add_display(3);
- } else {
- weatherDisplayChange = 0;
- displayMode = 0;
- }
- }
- }
- }
- //Add an individual LED to the outer ring on display
- void add_display(int hours) {
- int num = 0;
- while (num < 8) { //Search for next unused spot in array
- if (ledsOn[num] == -1) {
- break;
- }
- num++;
- }
- ledsOn[num] = ledDemux[hours]; //Add to array
- }
- //Cycles through the LEDs that should be turned on
- void cycle_leds(void) {
- int numIter = 0;
- if (ledsOn[0] != -1) { //If == -1
- while (numIter < 8) { //search through 8 slots
- if (ledsOn[lastCycle] != -1) {
- //PORTB to be the array, turning on setting mode light if in setting mode,
- //ENABLE is to enable the demux
- PORTB = ledsOn[lastCycle] + ENABLE;
- lastCycle++;
- if (lastCycle == 8) { //reset lastCycle
- lastCycle = 0;
- }
- break;
- } else {
- lastCycle = 0;
- }
- numIter++;
- }
- }
- if ((displayMode == 1) && (seconds < ((dateDisplayChange + 3) % 60))) {
- PORTB |= 0x01;
- }
- }
- //Deal with current command in IR Array
- void deal_with_command(void) {
- //If command is set
- if(get_command() == SETTING_BTN) {
- enter_button_pressed();
- }
- //Specific Setting Modes (TIME, ALARM, DATE)
- //set spececificSet
- if(!specificSet) {
- if(get_command() == TIME_BTN) {
- timeSetting = 1;
- specificSet = 1;
- } else if (get_command() == ALARM_BTN) {
- alarmSetting = 1;
- specificSet = 1;
- } else if (get_command() == DATE_BTN) {
- dateSetting = 1;
- specificSet = 1;
- }
- }
- //PREVIOUS or NEXT
- //Only works if specifically set
- if((get_command() == NEXT_BTN) && specificSet) {
- next_button_pressed();
- } else if((get_command() == PREV_BTN) && specificSet) {
- prev_button_pressed();
- }
- PORTB = ledDemux[currentLedIndex] + settingMode + ENABLE;
- }
- //If previous button is pressed while in IR setting mode
- void prev_button_pressed(void) {
- int min = 0; //Lower bound of valid LED range (corresponds to LEDs on clock face)
- int max = 11; //Outer bound
- int skip = -1; //Used to limit range of inner 4 LEDs (e.g. 28 days - only 3 middle LEDs allowed)
- if(timeSetting) {
- //Time Setting
- if(!minutesSet) { //Setting minutes
- min = 0;
- max = 11;
- } else if((minutesSet) && !minuteResoSet) { //Setting minute resolution
- min = 12;
- max = 16;
- } else if (minuteResoSet) { //Setting AM/PM
- min = 0;
- max = 0;
- currentLedIndex = 0;
- //Meridian setting
- PORTD ^= 0b01000000; //Toggle AM/PM LED
- }
- }
- //Alarm Setting
- if(alarmSetting) {
- if(!hoursSet && !minutesSet) { //Set Hours or Minutes
- min = 0;
- max = 11;
- } else if((minutesSet) && !minuteResoSet) {
- //Setting minute reso
- min = 12;
- max = 16;
- } else if (minuteResoSet) { //Setting AM/PM
- min = 0;
- max = 0;
- currentLedIndex = 0;
- //Meridian setting
- PORTD ^= 0b01000000; //Toggle AM/PM LED
- }
- }
- //DATE SETTING
- if(dateSetting) {
- if(!yearSet) { //Setting year
- min = 0;
- max = 11;
- } else if(!yearResoSet) { //Setting year resolution
- min = 12;
- max = 16;
- } else if (!monthSet) { //Setting of month
- min = 0;
- max = 11;
- } else if(!daySet) { //Setting of Day
- if(month != 2) { //Not February
- min = 0;
- max = 6;
- } else { //February - Allow setting of up to 25 days
- min = 0;
- max = 5; //CHANGED
- }
- } else if(!dayResoSet) { //Setting Day Resolution
- if (month == 1 || month == 3 || month == 5 || month == 7 ||
- month == 8 || month == 10 || month == 12) {
- //MONTHS with 31 days
- if(day == 30) { //Limit to first LED
- //31 Days
- min = 12;
- max = 16;
- skip = 13; //Skip to this LED if at 16
- } else { //All 4 middle LEDs accessible
- min = 12;
- max = 16;
- }
- } else if (month == 4 || month == 6 || month == 9 || month == 11) {
- //MONTHS with 30 days
- if(day == 30) {
- currentLedIndex = 0; //Don't allow any setting of resolution
- return;
- } if (day < 30) { //Allow 4 LEDs accessible
- min = 12;
- max = 16;
- }
- //FEBRUARY
- } else if (tempLeap) { //Leap Year - February
- min = 12;
- max = 16;
- } else { //Not Leap Year - February
- if(day == 25) {
- //For 28 days
- min = 12;
- max = 16;
- skip = 15; //Skip to if at max
- } else {
- //Allow 4 LEDs accessible (day <= 20)
- min = 12;
- max = 16;
- }
- }
- }
- }
- //Check boundaries, else decrement
- if (currentLedIndex == min) {
- currentLedIndex = max;
- } else {
- //Decrement LED index
- currentLedIndex--;
- while ((skip != -1) && (currentLedIndex >= skip)) { //Skip to 'skip' value
- currentLedIndex--;
- }
- }
- }
- //If next button is pressed while in IR setting mode
- void next_button_pressed(void) {
- int min = 0;
- int max = 11;
- int skip = -1;
- //If setting minutes resolution, 12 - 16 LED indexes
- if(timeSetting) {
- if(!minutesSet) {
- min = 0;
- max = 11;
- } else if((minutesSet) && !minuteResoSet) {
- //Setting minute reso
- min = 12;
- max = 16;
- } else if (minuteResoSet) {
- min = 0;
- max = 0;
- currentLedIndex = 0;
- //Meridian setting
- PORTD ^= 0b01000000;
- }
- }
- //Alarm setting
- if(alarmSetting) {
- if(!hoursSet && !minutesSet) { //Setting hours or minutes
- min = 0;
- max = 11;
- } else if(!minuteResoSet) { //Setting Minute resolution
- min = 12;
- max = 16;
- } else if (minuteResoSet) { //Setting AM/PM
- min = 0;
- max = 0;
- currentLedIndex = 0;
- //Meridian setting
- PORTD ^= 0b01000000;
- }
- }
- //Date setting mode
- if(dateSetting) {
- if(!yearSet) { //Setting year
- min = 0;
- max = 11;
- } else if(!yearResoSet) { //Setting year resolution
- min = 12;
- max = 16;
- } else if (!monthSet) { //Setting months
- min = 0;
- max = 11;
- }else if(!daySet) {
- if(month != 2) {
- min = 0;
- max = 6;
- } else {
- //February
- min = 0;
- max = 5; //CHANGED
- }
- } else if(!dayResoSet) {
- if (month == 1 || month == 3 || month == 5 || month == 7 ||
- month == 8 || month == 10 || month == 12) {
- if(day == 30) {
- //31 Days - only allow first 1 of 4 middle LEDs to select
- min = 12;
- max = 16;
- skip = 13;
- } else {
- //Allow all middle LEDs to be accessible
- min = 12;
- max = 16;
- }
- } else if (month == 4 || month == 6 || month == 9 || month == 11) {
- if(day == 30) { //CHANGED
- //Don't allow setting of day resolution
- currentLedIndex = 0;
- return;
- } else if (day < 30) {
- //Allow access of all middle LEDs
- min = 12;
- max = 16;
- }
- } else if (tempLeap) {
- //Leap year, 29 days (allow all 4 LEDs to be accessed)
- min = 12;
- max = 16;
- } else {
- if(day == 25) {
- //For 28 days - allow 3 out of 4 LEDs to be accessed
- min = 12;
- max = 16;
- skip = 15;
- } else {
- //Allow all LEDs to be accessed ( <= 20 days)
- min = 12;
- max = 16;
- }
- }
- }
- }
- //Check boundaries, else increment
- if (currentLedIndex == max) { //If at maximum, put LED at start of bounds (min)
- currentLedIndex = min;
- } else {
- //Increment ledIndex
- currentLedIndex++;
- if (currentLedIndex == skip) { //If need to skip LEDs
- currentLedIndex = max;
- }
- }
- }
- //Setting mode for IR (when SET is sent for the first time)
- void setting_mode(void) {
- currentLedIndex = 0; //Display top middle LED
- PORTB |= 0b00000001; //turn setting LED on
- PORTD &= 0xBF;
- clear_leds(); //Clear display LEDs
- while(1) {
- /* Turn off alarms */
- PORTC &= 0b11111101;
- alarmNow = 0;
- buzzCount = 0;
- buzzPrev = 0;
- PORTB = ledDemux[currentLedIndex] + settingMode + ENABLE; //Update PORTB (enable, setting LED and selected LED
- if(!timeSetting) {
- update_time(); //Still update the time if we're not setting the time
- update_time_variables(); //Update time variables (seconds, minutes, hours etc.)
- }
- //Setting mode finished
- if(!settingMode) {
- PORTB &= 0b11111110; //turn setting LED off
- specificSet = 0;
- break;
- }
- }
- }
- //SET button pressed via infrared remote, while in IR setting mode (settingMode == 1)
- void enter_button_pressed(void) {
- //The SET button is pressed to 'enter' or 'select' a value
- if (timeSetting) {
- set_time();
- }
- if (alarmSetting) {
- set_alarm();
- }
- if (dateSetting) {
- set_date();
- }
- }
- //DATE setting for Infrared Remote
- void set_date(void) {
- if(!yearSet) {
- year = 2000 + currentLedIndex * 5; //Increment 2000 by value of selected LED and set year
- yearSet = 1;
- currentLedIndex = 16;
- } else if (!yearResoSet) {
- //If year resolution is not 0, increment minutes accordingly
- if (currentLedIndex != 0 && currentLedIndex != 16) {
- year += (currentLedIndex - 11); //Increment year by value of selected LED
- }
- if ((year % 4) == 0) { //Leap year ?
- tempLeap = 1;
- }
- yearResoSet = 1;
- currentLedIndex = 1;
- } else if (!monthSet) { //Setting months
- if(currentLedIndex) { //If not on topMiddle LED (12th month)
- month = currentLedIndex;
- } else {
- month = 12;
- }
- monthSet = 1;
- currentLedIndex = 0;
- } else if (!daySet) { //Setting days
- day = 5 * currentLedIndex; //Set day to value of selected LED
- daySet = 1;
- currentLedIndex = 16;
- } else {
- if (currentLedIndex != 0 && currentLedIndex != 16) { //If not LED value of '0'
- day += (currentLedIndex - 11); //Increment days by value of selected LED
- }
- currentLedIndex = 0;
- tempLeap = 0;
- daySet = 0;
- yearSet = 0;
- monthSet = 0;
- yearResoSet = 0;
- specificSet = 0;
- dateSetting = 0;
- settingMode = 0;
- }
- }
- //TIME setting for Infrared remote
- void set_time(void) {
- if(!hoursSet) { //Set hours
- changeHours = currentLedIndex; //Set hours to selected LED value
- hoursSet = 1;
- currentLedIndex = 0;
- } else if(!minutesSet) { //Set Minutes
- if(currentLedIndex > 0) {
- changeMinutes = 5 * currentLedIndex; //Set minutes to selected LED value
- } else if (currentLedIndex == 0) {
- //On 12 location
- changeMinutes = 0;
- }
- minutesSet = 1;
- currentLedIndex = 16;
- } else if(!minuteResoSet){ //Setting minute resolution
- //If minute resolution is not 0, increment minutes accordingly
- if (currentLedIndex != 0 && currentLedIndex != 16) { //If not LED value of '0'
- changeMinutes += (currentLedIndex - 11); //Increment minutes by resolution (20 + 1 (reso) = 21 minutes)
- }
- minuteResoSet = 1;
- currentLedIndex = 0;
- } else {
- //Set ampm
- if((PORTD & 0b01000000) == 0b01000000) { //Take AM/PM value based whether AM/PM LED on
- changeAmpm = 1; //pm
- } else {
- changeAmpm = 0; //am
- }
- //Reset all varaibles
- changeSeconds = 0;
- tempLeap = 0;
- settingMode = 0;
- hoursSet = 0;
- minutesSet = 0;
- minuteResoSet = 0;
- specificSet = 0;
- currentLedIndex = 0;
- timeSetting = 0;
- set_rtc_time();
- }
- }
- /* SETTING ALARMS for Infrared Remote
- (NOTE, only temporary variables are set, not time variables (hours, minutes etc.)
- add_current_alarm(void) then takes these values and adds the actual alarm
- */
- void set_alarm(void) {
- if(!hoursSet) { //Setting hours
- tempHours = currentLedIndex; //Set tempHours to value of selected LED
- hoursSet = 1;
- currentLedIndex = 0;
- } else if(!minutesSet) { //Set Minutes
- if(currentLedIndex > 0) {
- tempMinutes = 5 * currentLedIndex ; //Set tempMnutes to value of selected LED
- } else if (currentLedIndex == 0) {
- //On 12 location
- tempMinutes = 0;
- }
- minutesSet = 1;
- currentLedIndex = 16;
- } else if(!minuteResoSet){ //Setting minute resolution
- //If minute resolution is not 0, increment minutes accordingly
- if (currentLedIndex != 0 && currentLedIndex != 16) { //If not LED value of '0'
- tempMinutes += (currentLedIndex - 11); //Increment tempMinutes by value of selected LED
- }
- minuteResoSet = 1;
- currentLedIndex = 0;
- } else {
- //Set ampm
- if((PORTD & 0b01000000) == 0b01000000) { //AM/PM depending on whether AM/PM light on
- tempMeridian = 1;
- } else {
- tempMeridian = 0;
- }
- add_current_alarm(); //Add alarms with 'temp' variable values
- tempHours = 0;
- tempMinutes = 0;
- tempMeridian = 0;
- settingMode = 0;
- hoursSet = 0;
- minutesSet = 0;
- minuteResoSet = 0;
- specificSet = 0;
- currentLedIndex = 0;
- alarmSetting = 0;
- }
- }
- //Checks to see if there is an alarm that needs to be triggered
- void check_for_alarm(void) {
- int alarmValue = (minutes*60) + (hours * 60 * 60); //Alarms stored as seconds
- int found = 0; //Whether an alarm has been found
- //Iterate through the alarm array
- for(int i = 0; i < 10; i++ ) {
- //if alarm is now
- if((alarms[i] == alarmValue) && (alarmMeridians[i] == ampm)) {
- found = 1;
- alarms[i] = -1; //reset that alarm
- alarmMeridians[i] = -1;
- alarmNow = 1; //Is there an alarm that should be on now
- buzzPrev = seconds;
- buzzCount = 3; //turn on buzzer for 3 seconds
- break;
- }
- }
- //Remove any other alarms at the same time
- if(found) {
- for(int i = 0; i < 10; i++ ) {
- if((alarms[i] == alarmValue) && (alarmMeridians[i] == ampm)) {
- alarms[i] = -1;
- alarmMeridians[i] = -1;
- }
- }
- }
- }
- //Adds the alarm currently stored in global variables
- void add_current_alarm(void) {
- int alarmValue = (tempMinutes*60) + (tempHours* 60 * 60); //Alarm in seconds
- for(int i = 0; i < 10; i++) {
- //Find first free alarm slot and store alarm
- if(alarms[i] == -1) {
- alarms[i] = alarmValue;
- alarmMeridians[i] = tempMeridian;
- break;
- }
- }
- }
- //Clear the ledsOn array
- void clear_leds(void) {
- for(int i = 0; i < 8; i++) {
- ledsOn[i] = -1;
- }
- }
- //Get the command currently stored in irArray and return as a 8bit char
- char get_command(void) {
- char temp = 0;
- for (int i = 0; i < 8; i++) {
- temp |= (irArray[i] << (7-i));
- }
- return temp;
- }
- //Checks to see if the Optical clock pin has changed since the last read
- void check_clock(void) {
- //If clock has been in optical setting mode for more than 25 seconds, reset clock
- if ((adcSettingStart != -1) && (seconds == ((adcSettingStart + 29) % 60))) {
- reset_clock();
- adcSettingMode = 0;
- specificSet = 0;
- weatherSetting = 0;
- timeSetting = 0;
- dateSetting = 0;
- alarmSetting = 0;
- adcSettingStart = -1;
- }
- //If value in ADC register is >675 it is a logical 0, else 1
- if (ADC > 675) {
- currentADC = 0;
- } else {
- currentADC = 1;
- }
- //If changed since last read
- if (currentADC != oldADC) {
- oldADC = currentADC; //Update varaible
- adcDelay = 0; //Start delay until next read
- if (adcCount == 0) {
- adcCommandStart = seconds;
- }
- read_data();
- }
- }
- //Reads data off Optical data pin
- void read_data(void) {
- //Change ADC multiplexer register
- ADMUX = 0x42;
- //Complete previous read
- while ((ADCSRA & 0x40) != 0x00);
- //Start read with new multiplexer value
- ADCSRA |= 0x40;
- //Wait for that read to complete
- while ((ADCSRA & 0x40) != 0x00);
- if (ADC > 675) { //Store result in adcArray
- adcArray[adcCount] = 0;
- } else {
- adcArray[adcCount] = 1;
- }
- if (adcCount < 8) {
- adcCount++;
- }
- //If full command recieved
- if (adcCount == 8) {
- //If set command while not in setting mode
- if(!adcSettingMode && (get_adc() == SETTING_BTN)) {
- //If not in IR setting mode
- if(!settingMode) {
- adcSettingMode = 1; //Optical Setting
- adcSettingStart = seconds; //Start counting the 25 seconds
- }
- } else if (adcSettingMode) {
- deal_with_adc(); //Process command
- }
- adcCount = 0; //Reset the array
- clear_adc();
- adcCommandStart = -1; //Clear timeout counter
- }
- while ((ADCSRA & 0x40) != 0x00); //Complete current Read
- ADMUX = 0x40; //Change register back
- ADCSRA |= 0x40;
- while ((ADCSRA & 0x40) != 0x00); //Wait for another read
- }
- //Clears AdcArray
- void clear_adc(void) {
- for (int i = 0; i < 8; i++) {
- adcArray[i] = -1;
- }
- adcCount = 0;
- }
- // Setting mode for the GUI data transfer, (when first SET signal is received)
- void adc_setting_mode(void) {
- //TODO: Turn on Setting LED
- while(1) {
- /* Turn off alarms */
- PORTC &= 0b11111101;
- alarmNow = 0;
- buzzCount = 0;
- buzzPrev = 0;
- PORTB = ledDemux[0] + ENABLE; //Put top middle LED on whilst setting ADC
- PORTB |= 0x01;
- PORTD &= 0xBF;
- if (((ADCSRA & 0x40) == 0) && (adcDelay == -1)) { //Whilst still converting ADC
- ADCSRA |= 0x40;
- while ((ADCSRA & 0x40) != 0x00);
- check_clock(); //Check if the clock has changed
- }
- //Still update time whilst in setting mode
- update_time();
- update_time_variables();
- if(!adcSettingMode) {
- break;
- }
- }
- }
- //When a signal is received whilst in GUI data transfer setting mode (adcSetting == 1)
- void deal_with_adc(void) {
- //Deal with current command in IR Array
- if(get_adc() == SETTING_BTN) {
- adc_set(); //NOTE: This uses the value of the PREVIOUS signal for adcNum
- }
- //Determine the signal received from GUI
- // algorithms used to extract integer value from binary below:
- int adc1 = 128 - get_adc();
- int adc2 = 64 - get_adc();
- if ((adc1 > 0) && (adc1 < 33)) {
- adcNum = adc1;
- } else if ((adc2 > 30) && (adc2 < 61)) {
- if (adc2 == 60) {
- adcNum = 0;
- } else {
- adcNum = adc2;
- }
- } else if ((get_adc() > -1) && (get_adc() < 3)) {
- adcNum = get_adc();
- }
- //Specific Setting Modes (TIME, ALARM, DATE, WEATHER)
- if(!specificSet) {
- if(get_adc() == TIME_BTN) {
- timeSetting = 1;
- specificSet = 1;
- } else if (get_adc() == ALARM_BTN) {
- alarmSetting = 1;
- specificSet = 1;
- } else if(get_adc() == DATE_BTN) {
- dateSetting = 1;
- specificSet = 1;
- } else if(get_adc() == WEATHER_SET) {
- weatherSetting = 1;
- specificSet = 1;
- }
- }
- clear_adc();
- adcCommandStart = -1;
- }
- //SET signal received from GUI, while in adcSetting mode
- void adc_set(void) {
- //The SET signal is received from GUI (via adc) whilst in setting mode
- if(timeSetting) {
- adc_set_time();
- }
- if(alarmSetting) {
- adc_set_alarm();
- }
- if(dateSetting) {
- adc_set_date();
- }
- if(weatherSetting) {
- adc_weather_set();
- }
- }
- //GUI Data Transfer - WEATHER SETTING
- void adc_weather_set(void) {
- if(adcNum == 2) {
- //FINE
- weatherType = 0;
- } else if (adcNum == 1) {
- //CLOUDY
- weatherType = 2;
- } else if (adcNum == 0) {
- //RAINY
- weatherType = 1;
- }
- //Finish setting mode since only one signal needed
- weatherSetting = 0;
- weatherDisplayChange = seconds;
- displayMode = 2;
- adcSettingMode = 0;
- specificSet = 0;
- adcSettingStart = -1;
- }
- //GUI Data Transfer - DATE SETTING
- void adc_set_date(void) {
- if(!yearSet) { //Set years
- adcYear = 2000 + adcNum; //Set year to that of the read value from GUI
- yearSet = 1;
- } else if (!monthSet) { //Set month to that of the read value from GUI
- adcMonth = adcNum;
- monthSet = 1;
- } else { //Set day and finished setting mode
- day = adcNum;
- year = adcYear;
- month = adcMonth;
- yearSet = 0;
- monthSet = 0;
- specificSet = 0;
- adcSettingMode = 0;
- dateSetting = 0;
- adcSettingStart = -1;
- }
- }
- //GUI Data Transfer - TIME SETTING
- void adc_set_time(void) {
- //NOTE: adcNum is the value of the previous signal (before SET was sent)
- if(!hoursSet) { //Set hours in 24 hours
- if((adcNum - 12) >= 0) { //In 24 hour time - meaning greater than 12 is PM
- //PM
- adcHours = adcNum - 12;
- adcAmpm = 1;
- } else {
- //AM
- adcHours = adcNum;
- adcAmpm = 0;
- }
- hoursSet = 1;
- } else { //Set minutes and finish setting mode
- adcMinutes = adcNum;
- changeHours = adcHours;
- adcHours = 0;
- hoursSet = 0;
- changeMinutes = adcMinutes;
- adcMinutes = 0;
- changeAmpm = adcAmpm;
- adcAmpm = 0;
- changeSeconds = 0;
- timeSetting = 0;
- specificSet = 0;
- adcSettingMode = 0;
- adcSettingStart = -1;
- set_rtc_time();
- }
- }
- //ALARM setting for GUI data transfer
- void adc_set_alarm(void) {
- //NOTE: adcNum is the value of the previous signal (before SET was sent)
- if(!hoursSet) { //Setting hours
- if((adcNum - 12) >= 0) { //Since in 24-hour time, if greater than 12, PM
- //PM
- tempMeridian = 1;
- tempHours = adcNum - 12;
- } else {
- //AM
- tempMeridian = 0;
- tempHours = adcNum;
- }
- hoursSet = 1;
- } else { //Set minutes and finish setting mode
- tempMinutes = adcNum;
- add_current_alarm(); //Add alarm via use of 'temp' variables
- tempMinutes = 0;
- tempHours = 0;
- tempMeridian = 0;
- adcSettingMode = 0;
- hoursSet = 0;
- specificSet = 0;
- alarmSetting = 0;
- adcSettingStart = -1;
- }
- }
- //Returns an 8bit char representation of the array currently stored in adcArray
- char get_adc(void) {
- char temp = 0;
- for (int i = 0; i < 8; i++) {
- temp |= (adcArray[i] << (7-i));
- }
- return temp;
- }
- //Updates time global variables
- void update_time_variables(void) {
- //If seconds have changed from the last time
- if(seconds != oldSeconds) {
- //update vars
- oldSeconds = seconds;
- if ((seconds == 0) && (minutes == 0) && (hours == 0) && (ampm == 0)) { //update ampm and days
- day++;
- } //Update month
- if (month == 1 || month == 3 || month == 5 || month == 7 ||
- month == 8 || month == 10 || month == 12) {
- if (day == 32) { //Months with 31 days - if next month
- month++;
- day = 0;
- }
- } else if (month == 4 || month == 6 || month == 9 || month == 11) {
- if (day == 31) { //Months with 30 days - if next month
- month++;
- day = 0;
- }
- } else if ((year % 4) == 0) { //If leap year (february)
- if (day == 30) { //If next month
- month++;
- day = 0;
- }
- } else {
- if (day == 29) { //Not leap year, 29 days in february
- month++;
- day = 0;
- }
- } //update year
- if (month == 13) {
- year++;
- month = 0;
- }
- }
- }
- //Resets the time variables in the event of an Optical timeout.
- void reset_clock(void) {
- seconds = 0;
- minutes = 0;
- hours = 0;
- day = 1;
- month = 1;
- year = 2012;
- ampm = 0;
- }
- // Convert Decimal to Binary Coded Decimal (BCD)
- char dec2bcd(char num) {
- return ((num/10 * 16) + (num % 10));
- }
- // Convert Binary Coded Decimal (BCD) to Decimal
- char bcd2dec(char num) {
- return ((num/16 * 10) + (num % 16));
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement