/* ****************************************************************************
* PIC to Pi ユーティリティー
*
* inerval_timer.c
*
* retrun 0 : nomal end
* retrun 1 : sigaction error
* retrun 2 : setitimer error
*                                                        2013.2.9 shellvalley
*******************************************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/time.h>
#include <signal.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>

uint8_t T1_10msec_sign;
uint8_t T2_10msec_sign;
uint8_t T3_10msec_sign;
uint8_t T1_100msec_sign;
uint8_t T1_1sec_sign;
uint8_t T1_3sec_sign;
uint8_t T1_10sec_sign;
uint8_t T1_60sec_sign;
uint8_t T1_600sec_sign;

int32_t T1_10msec_cnt;
int32_t T2_10msec_cnt;
int32_t T3_10msec_cnt;
int32_t T1_100msec_cnt;
int32_t T1_1sec_cnt;
int32_t T1_3sec_cnt;
int32_t T1_10sec_cnt;
int32_t T1_60sec_cnt;

void SignalHandler(int);          // SIGALRMシグナルを通知された時に起動してもらう関数
int _nanosleep(int, int);
void rsp_timer1_init(void);

// ############################################################################
int set_interval_timer(void){           // 10000 usec:10ms
        struct sigaction action;
        struct itimerval timer;
        memset(&action, 0, sizeof(action));
        action.sa_handler = SignalHandler;
        action.sa_flags = SA_RESTART;
        sigemptyset(&action.sa_mask);

        if(sigaction(SIGALRM, &action, NULL) < 0){
                return(1);
        }
        rsp_timer1_init();
        rsp_timer2_init();
        rsp_timer3_init();
//set intarval timer (10ms)************************
        timer.it_value.tv_sec = 0;
        timer.it_value.tv_usec = 10000;                         // 10 msec
//      timer.it_value.tv_usec = nn;
        timer.it_interval.tv_sec = 0;
        timer.it_interval.tv_usec = 10000;
//      timer.it_interval.tv_usec = nn;
        if(setitimer(ITIMER_REAL, &timer, NULL) < 0){
                return(2);
        }
    return(0);
}
// ############################################################################
void SignalHandler(int signum){
        T1_10msec_sign = 1;                                      // 10msec
        T2_10msec_sign = 1;                                      // 10msec
        T3_10msec_sign = 1;                                      // 10msec
        T1_10msec_cnt++;
        T2_10msec_cnt++;
        T3_10msec_cnt++;
        if(!(T1_10msec_cnt % 10)){
                T1_100msec_sign = 1;                             // 100msec
                T1_100msec_cnt++;
        }
        if(!(T1_10msec_cnt % 100)){
                T1_1sec_sign = 1;                                // 1sec
                T1_1sec_cnt++;
        }
        if(!(T1_10msec_cnt % 300)){
                T1_3sec_sign= 1;                                 // 3sec
                T1_3sec_cnt++;
        }
        if(!(T1_10msec_cnt % 1000)){
                T1_10sec_sign= 1;                                // 10sec
                T1_10sec_cnt++;
        }
        if(!(T1_10msec_cnt % 6000)){
                T1_60sec_sign= 1;                                // 60sec
                T1_60sec_cnt++;
        }
        if(!(T1_10msec_cnt % 60000)){
                T1_600sec_sign= 1;                               // 600sec
                T1_10msec_cnt = 0;
                T1_100msec_cnt = 0;
                T1_1sec_cnt = 0;
                T1_3sec_cnt = 0;
                T1_10sec_cnt = 0;
                T1_60sec_cnt = 0;
        }
}
// ############################################################################
int _nanosleep(int sec, int nsec){
    struct timespec req, rem;
        req.tv_sec = sec;
        req.tv_nsec = nsec;
        rem.tv_sec = 0;
        rem.tv_nsec = 0;
        while(nanosleep(&req, &rem)){
        if(errno == EINTR){
            req.tv_sec = rem.tv_sec;
            req.tv_nsec = rem.tv_nsec;
        }else{
            perror("nanosleep error");
            return -1;
        }
    }
    return 0;
}
// ############################################################################
void rsp_timer1_init(void){
        T1_10msec_sign  = 0;
        T1_100msec_sign = 0;
        T1_1sec_sign    = 0;
        T1_3sec_sign    = 0;
        T1_10sec_sign   = 0;
        T1_60sec_sign   = 0;
        T1_600sec_sign  = 0;
        T1_10msec_cnt   = 0;
        T1_100msec_cnt  = 0;
        T1_1sec_cnt     = 0;
        T1_3sec_cnt     = 0;
        T1_10sec_cnt    = 0;
        T1_60sec_cnt    = 0;
}
// ############################################################################
void rsp_timer2_init(void){
        T2_10msec_sign  = 0;
        T2_10msec_cnt   = 0;
}
// ############################################################################
void rsp_timer3_init(void){
        T3_10msec_sign  = 0;
        T3_10msec_cnt   = 0;
}
// ############################################################################