I2C hang recover function added

Dependencies:   UniGraphic mbed vt100

In this version, check_i2c_pins function was added in edge_mgr.cpp.

プログラムの起動時、I2Cモジュールを初期化する前に、I2Cに使用するピンの電位を確認し
もし一方でも Low に張り付いていた場合、SCL を GPIO 出力に設定して 
所定回数 (I2C_UNLOCK_TRIAL_CYCLE) 反転させることにより、疑似リセットクロックを生成します。

その後は、通常の起動手順に復帰し、以降はこれまでと同様の動作をします。

edge_utils/edge_time.cpp

Committer:
Rhyme
Date:
2018-04-03
Revision:
0:d895cd1cd897

File content as of revision 0:d895cd1cd897:

#include "mbed.h"
#include "edge_time.h"

static const uint8_t daysInMonth[12] = {
    31, 28, 31, 30,
    31, 30, 31, 31,
    30, 31, 30, 31
} ;

const char *nameOfDay[7] = {
    "Sunday", "Monday", "Tuesday", "Wednesday", 
    "Thursday", "Friday", "Saturday"
} ;

uint32_t edge_time = 0 ;
uint32_t utc_offset = 9 * 60 * 60 ;
tm current_time ;
Ticker *tokei = 0 ;

void inc_sec(void)
{
    __disable_irq() ; // Disable Interrupts
    edge_time++ ;
    __enable_irq() ; // Enable Interrupts
}

void init_timer(void)
{
    tokei = new Ticker() ;
    tokei->attach(inc_sec, 1.0) ;
}

void set_time(const uint16_t  valueLen, const uint8_t *value) 
{
    uint32_t tmp_timestamp = 0 ;
    for (int i = 0 ; i < valueLen ; i++ ) {
        tmp_timestamp |= (value[i] & 0xFF) << (i * 8) ;
    }
    edge_time = tmp_timestamp ;
    ts2tm(edge_time, &current_time) ;
//    ts2time(edge_time, &current_time) ;
}

void ts2time(uint32_t timestamp, struct tm *tm)
{
    uint32_t seconds, minutes, hours, days, month, year ;
    uint32_t dayOfWeek ;
    
//    timestamp += (3600 * 9) ; /* +9 hours for JST */
    timestamp += utc_offset ;
    
    seconds = timestamp % 60 ;
    minutes = timestamp / 60 ;
    hours   = minutes / 60  ; /* +9 for JST */
    minutes -= hours * 60 ;
    days    = hours / 24 ;
    hours   -= days * 24 ;
    
    tm->tm_sec = seconds ;
    tm->tm_min = minutes ;
    tm->tm_hour = hours ; 
    tm->tm_mday = days + 1 ;
//    tm->tm_mon  = month ;
//    tm->tm_year = year ;
//    tm->tm_wday = dayOfWeek ;
}

void ts2tm(uint32_t timestamp, struct tm *tm)
{
    uint32_t seconds, minutes, hours, days, month, year ;
    uint32_t dayOfWeek ;
    
//    timestamp += (3600 * 9) ; /* +9 hours for JST */
    timestamp += utc_offset ;
    
    seconds = timestamp % 60 ;
    minutes = timestamp / 60 ;
    hours   = minutes / 60  ; /* +9 for JST */
    minutes -= hours * 60 ;
    days    = hours / 24 ;
    hours   -= days * 24 ;
    
    /* Unix timestamp start 1-Jan-1970 Thursday */
    year = 1970 ;
    dayOfWeek = 4 ; /* Thursday */
    
    while(1) {
        bool isLeapYear = 
            (((year % 4) == 0)
            &&(((year % 100) != 0)
            || ((year % 400) == 0))) ;
        uint16_t daysInYear = isLeapYear ? 366 : 365 ;
        if (days >= daysInYear) {
            dayOfWeek += isLeapYear ? 2 : 1 ;
            days      -= daysInYear ;
            if (dayOfWeek >= 7) {
                dayOfWeek -= 7 ;
            }
            year++ ;
        } else {
            tm->tm_yday = days ;
            dayOfWeek += days ;
            dayOfWeek %= 7 ;
            
            /* calc the month and the day */
            for (month = 0 ; month < 12 ; month++) {
                uint8_t dim = daysInMonth[month] ;
                
                /* add a day to feburary if this is a leap year */
                if ((month == 1) && (isLeapYear)) {
                    dim++ ;
                }
                
                if (days >= dim) {
                    days -= dim ;
                } else {
                    break ;
                }
            }
            break ;
        }
    }
    tm->tm_sec = seconds ;
    tm->tm_min = minutes ;
    tm->tm_hour = hours ; 
    tm->tm_mday = days + 1 ;
    tm->tm_mon  = month ;
    tm->tm_year = year ;
    tm->tm_wday = dayOfWeek ;
}

void print_time(struct tm *tm)
{
    printf("%02d:%02d:%02d",
        tm->tm_hour,
        tm->tm_min,
        tm->tm_sec ) ;
}

void print_time(uint32_t thetime) 
{
    struct tm timestruct ;
    ts2time(thetime, &timestruct) ;
    print_time(&timestruct) ;
}

void print_time(void)
{
    struct tm timestruct ;
    ts2time(edge_time, &timestruct) ;
    print_time(&timestruct) ;
}

void print_date(struct tm *tm) 
{
    printf("%d/%d/%d %02d:%02d:%02d",
        tm->tm_year,
        tm->tm_mon + 1,
        tm->tm_mday,
        tm->tm_hour,
        tm->tm_min,
        tm->tm_sec
        ) ;
}

void print_date_wd(struct tm *tm) 
{
    printf("%d/%d/%d %02d:%02d:%02d (%s)",
        tm->tm_year,
        tm->tm_mon + 1,
        tm->tm_mday,
        tm->tm_hour,
        tm->tm_min,
        tm->tm_sec,
        nameOfDay[tm->tm_wday]
        ) ;
}

void time2str(struct tm *tm, char *timestr) 
{
    sprintf(timestr, "%02d:%02d:%02d",
        tm->tm_hour,
        tm->tm_min,
        tm->tm_sec ) ;
}

void time2str(char *timestr)
{
    struct tm timestruct ;
    ts2time(edge_time, &timestruct) ;
    time2str(&timestruct, timestr) ;
}

int32_t time2seq(uint32_t timestamp)
{
    struct tm timestruct ;
    int32_t result  ;
    ts2time(timestamp, &timestruct) ;
    result = timestruct.tm_hour * 10000 
        + timestruct.tm_min * 100
        + timestruct.tm_sec ;
    return(result) ;
}

void time2seq(uint32_t timestamp, char *timestr) 
{
    struct tm timestruct ;
    ts2tm(timestamp, &timestruct) ;
    sprintf(timestr, "%d%02d%02d%02d%02d%02d",
        timestruct.tm_year,
        timestruct.tm_mon + 1,
        timestruct.tm_mday,
        timestruct.tm_hour,
        timestruct.tm_min,
        timestruct.tm_sec
    ) ;
}

void time2date(struct tm *tm, char *datestr)
{
    sprintf(datestr, "%d/%d/%d %02d:%02d:%02d (%s)",
        tm->tm_year,
        tm->tm_mon + 1,
        tm->tm_mday,
        tm->tm_hour,
        tm->tm_min,
        tm->tm_sec,
        nameOfDay[tm->tm_wday]
    ) ;
}