Source

loolog.avr / clock.c

Full commit
/**
  * @author      $Author: Sven Hendriks <sven@loolog.org> $ (Sven Hendriks)
  * @copyright   (c) 2009 Sven Hendriks
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include "clock.h"

const uint8_t sevenSegData[CLOCK_MAX_BASE] = {
  0b00111111, // 0
  0b00000110, // 1
  0b01011011, // 2
  0b01001111, // 3
  0b01100110, // 4
  0b01101101, // 5
  0b01111101, // 6
  0b00000111, // 7
  0b01111111, // 8
  0b01101111, // 9
  0b01110111, // A
  0b01111100, // b
  0b00111001, // C
  0b01011110, // d
  0b01111001, // E
  0b01110001, // F
  0b00111101, // G
  0b01110110, // H
  0b00110000, // I
  0b00011110  // J
};

/*struct {
    uint16_t year;
    uint8_t  month, day, hour, minute, second, weekDay, daySavingTime;
} dateTime;
*/

uint8_t displayData[14] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0};

void clock_init(void) {
    dateTime.year     = 1970;
    dateTime.month    = 1;
    dateTime.day      = 1;
    dateTime.hour     = 0;
    dateTime.minute   = 0;
    dateTime.second   = 0;
    dateTime.weekDay  = 0;
    dateTime.daySavingTime = 0;
}

void clock_incOneSec(void) {
    dateTime.second++;
    if(dateTime.second >= 60) {
        dateTime.second = 0;
        dateTime.minute++;
        if(dateTime.minute >= 60) {
            dateTime.minute = 0;
            dateTime.hour++;
            if(dateTime.hour >= 24) {
                dateTime.hour = 0;
                dateTime.day += 1;
                if(   (dateTime.month == 2 && dateTime.day > 28)
                   || ((   dateTime.month == 1 || dateTime.month == 3
                        || dateTime.month == 5 || dateTime.month == 7
                        || dateTime.month == 8 || dateTime.month == 10
                        || dateTime.month == 12) && dateTime.day > 31)
                   || ((   dateTime.month == 4 || dateTime.month == 6
                        || dateTime.month == 9 || dateTime.month == 11)
                        && dateTime.day > 30)) {
                    dateTime.day = 1;
                    dateTime.month += 1;
                    if(dateTime.month > 12) {
                        dateTime.month = 1;
                        dateTime.year += 1;
                    }
                }

            }
        }
    }
}

void clock_setDateTime(uint16_t year,     uint8_t month,  uint8_t day, 
                           uint8_t  hour,     uint8_t minute, uint8_t second, 
                           uint8_t  week_day, uint8_t day_saving_time) {
    dateTime.year    = year;
    dateTime.month   = month;
    dateTime.day     = day;
    dateTime.hour    = hour;
    dateTime.minute  = minute;
    dateTime.second  = second;
    dateTime.weekDay = week_day;
    dateTime.daySavingTime = day_saving_time;
}

uint16_t pow2(uint16_t base, uint16_t exp) {
    uint16_t i, p = 1;
    for(i=0; i<exp; i++) p *= base;
    return p;
}

void iToDigits(uint16_t i, uint8_t no_of_digits, uint8_t base, uint8_t *result) {
    volatile uint16_t divisor;
    volatile uint8_t last_digit, digit_pos, digit;

    if(NULL != result && 1 <= no_of_digits) {
        divisor = pow2(base, no_of_digits-1);
        last_digit = 0;
        for(digit_pos = 0; digit_pos < no_of_digits; digit_pos++) {
            digit = (uint8_t) i / divisor - last_digit * base;
            if(digit < CLOCK_MAX_BASE) {
              *result = sevenSegData[digit];
            } else {
              *result = 0b01001001;
            }
            result++;
            last_digit = digit;
            divisor /= base;
        } 
    }
}

uint8_t* clock_to7SegmentData(uint8_t base) {
    // convert date and time into a string
    // the bytes of this string can be used
    // to drive 7 segment display elements
    // directly
    iToDigits(dateTime.year,   4, base, &displayData[ 0]);
    iToDigits(dateTime.month,  2, base, &displayData[ 4]);
    iToDigits(dateTime.day,    2, base, &displayData[ 6]);
    iToDigits(dateTime.hour,   2, base, &displayData[ 8]);
    iToDigits(dateTime.minute, 2, base, &displayData[10]);
    iToDigits(dateTime.second, 2, base, &displayData[12]);
    return displayData;
}

void clock_toStr(uint8_t *str) {
    sprintf(str, "%04d-%02d-%02d %02d:%02d:%02d %d %d",
            dateTime.year + 2000, dateTime.month,  dateTime.day,
            dateTime.hour,        dateTime.minute, dateTime.second,
            dateTime.weekDay,     dateTime.daySavingTime);
}