
#define _SUPPRESS_PLIB_WARNING
#define _DISABLE_OPENADC10_CONFIGPORT_WARNING
#include <plib.h>
#include "alarms.h"
#include "mainmenu.h"
#include <string.h>


__attribute__((mips16)) void toggle_global_alarm_flag() {
    char temp[6];
    memcpy(temp, alarm_submenu[0].name, 6);
    memcpy(alarm_submenu[0].name, alarm_submenu[0].data.altname, 6);
    memcpy(alarm_submenu[0].data.altname, temp, 6);
}

int alarm_timer, snooze;
static int alarm_duty, alarm_cadence_ctr, alarm_cadence_pos, snooze_wday;
static unsigned char alarm_cadence[6];
unsigned char alarm_is_daily_type;
__attribute__((mips16)) void alarm_trigger(rtccTime* time, unsigned char daily_type) {
    int i, temp, temp2, hz = PIEZO_PULSE_FREQ_HZ;

    alarm_timer = PIEZO_DURATION_SEC * hz;
    alarm_is_daily_type = daily_type;
    if( !hz || !alarm_timer ) {
        // alarm is disabled
        alarm_timer = 0;
        return;
    }
    IEC0bits.T1IE = 0;
    TMR1 = 0;
    PR1 = 32768 / (hz >= 1 && hz <= 10 ? hz : 1) - 1;
    IFS0bits.T1IF = 0;
    alarm_duty = PR1 * PIEZO_DUTY_PCT / 100;
    alarm_cadence_ctr = 0;
    alarm_cadence_pos = 0;
    temp = PIEZO_CADENCE;
    if( !temp )
        temp = 100000;
    for( i = 5; i >= 0; --i ) {
        temp2 = temp/10;
        alarm_cadence[i] = temp - temp2*10;
        temp = temp2;
    }
}

extern __attribute__((mips16)) void go_to_time_display();
__attribute__((mips16)) static unsigned char bcd_to_dec(unsigned char bcd) {
    return (bcd>>4)*10 + (bcd&0x0F);
}
__attribute__((mips16)) unsigned char alarm_get_piezo_state(rtccTime* time, rtccDate* date) {
    if( GLOBAL_ALARM_FLAG && ALARM_ON(snooze ? snooze_wday : date->wday) & !alarm_timer ) {
        int alarm_time = ALARM_TIME(snooze ? snooze_wday : date->wday);
        int hour, min, sec;

        hour = alarm_time / 10000;
        alarm_time -= hour * 10000;
        min = alarm_time / 100;
        sec = alarm_time - min * 100;

        min += snooze;
        while( min >= 60 ) {
            alarm_time += 10000;
            min -= 60;
            if( ++hour == 24 )
                hour = 0;
        }
        if( sec == bcd_to_dec(time->sec) && min == bcd_to_dec(time->min) && hour == bcd_to_dec(time->hour) ) {
            go_to_time_display();
            alarm_trigger(time, 1);
        }
    }
    if( alarm_timer ) {
        if( IFS0bits.T1IF ) {
            IFS0bits.T1IF = 0;
            ++alarm_cadence_ctr;
            while( alarm_cadence_ctr >= alarm_cadence[alarm_cadence_pos] ) {
                alarm_cadence_ctr = 0;
                if( ++alarm_cadence_pos == 6 )
                    alarm_cadence_pos = 0;
            }
            if( --alarm_timer == 0 ) {
                PR1 = 32768;
                TMR1 = 0;
                IEC0bits.T1IE = 1;
                go_to_time_display();
                return 0;
            }
        }
        // return non-zero to sound piezo
        return TMR1 < alarm_duty && !(alarm_cadence_pos&1);
    } else {
        return 0;
    }
}

__attribute__((mips16)) void alarm_snooze(rtccDate* date) {
    alarm_timer = 0;
    if( !snooze )
        snooze_wday = date->wday;
    snooze += 5;
}

__attribute__((mips16)) void alarm_cancel() {
    if( alarm_timer ) {
        alarm_timer = 0;
        PR1 = 32768;
        TMR1 = 0;
        IEC0bits.T1IE = 1;
    }
    snooze = 0;
}

__attribute__((mips16)) unsigned char alarm_is_in_next_24_hours(rtccTime* time, rtccDate* date) {
    int nextday, dectime, hour, min, wday;

    if( !GLOBAL_ALARM_FLAG )
        return 0;
    hour = time->hour;
    min = time->min;
    wday = date->wday;
    if( snooze ) {
        min -= snooze;
        while( min < 0 ) {
            min += 60;
            if( --hour < 0 ) {
                hour += 24;
                if( --wday < 0 )
                    wday = 6;
            }
        }
    }
    dectime = (hour * 100 + min) * 100 + time->sec;
    if( ALARM_ON(wday) && ALARM_TIME(wday) > dectime )
        return 1;
    nextday = wday == 6 ? 0 : wday + 1;
    if( ALARM_ON(nextday) && ALARM_TIME(nextday) < dectime )
        return 1;
    return 0;
}
/*
__attribute__((mips16)) unsigned char alarm_is_snoozed() {
    return snooze > 0;
}
*/