#include "vanne.h"

/*[[[cog
import conf
import avrxmegastuff as ams
]]]*/
//[[[end]]]


/*[[[cog
cog.out(
    ams.ev(
        prefix="vanne",
        **conf.VANNE,
        header=False,
    )
)
]]]*/
volatile ev_state_t vanne_internal_status;

void vanne_init()
{
    VANNE_CMD_PORT.DIRSET = VANNE_CMD_OPEN_bm | VANNE_CMD_CLOSE_bm;
    VANNE_CMD_PORT.OUTCLR = VANNE_CMD_OPEN_bm | VANNE_CMD_CLOSE_bm;
    VANNE_SENSOR_PORT.DIRCLR = VANNE_SENSOR_OPEN_bm | VANNE_SENSOR_CLOSE_bm;
    VANNE_SENSOR_OPEN_PINCTRL = PORT_OPC_PULLUP_gc;
    VANNE_SENSOR_CLOSE_PINCTRL = PORT_OPC_PULLUP_gc;
    vanne_internal_status = EV_MID;
}

uint8_t vanne_internal_step_close(uint16_t d)
{
    if(vanne_internal_status == EV_CLOSED)
        return 1;

    if(d<VANNE_ACTION_LIMIT)
        return 0;
    
    if(vanne_internal_status == EV_OPENED)
        d = 500;
    vanne_internal_status = EV_MID;
    
    vanne_callback_close();
    uint16_t k;
    VANNE_CMD_PORT.OUTSET = VANNE_CMD_CLOSE_bm;
    for(k=0;k<d;k++)
        _delay_ms(1);
    if(!(VANNE_SENSOR_PORT.IN & VANNE_SENSOR_CLOSE_bm))
        vanne_internal_status = EV_CLOSED;
    VANNE_CMD_PORT.OUTCLR = VANNE_CMD_CLOSE_bm;

    if(vanne_internal_status == EV_CLOSED)
        return 1;
    return 0;
}

uint8_t vanne_internal_step_open(uint16_t d)
{
    if(vanne_internal_status == EV_OPENED)
        return 1;

    if(d<VANNE_ACTION_LIMIT)
        return 0;
    
    if(vanne_internal_status == EV_CLOSED)
        d = 500;
    vanne_internal_status = EV_MID;
    
    vanne_callback_open();
    uint16_t k;
    VANNE_CMD_PORT.OUTSET = VANNE_CMD_OPEN_bm;
    for(k=0;k<d;k++)
        _delay_ms(1);
    if(!(VANNE_SENSOR_PORT.IN & VANNE_SENSOR_OPEN_bm))
        vanne_internal_status = EV_OPENED;
    VANNE_CMD_PORT.OUTCLR = VANNE_CMD_OPEN_bm;

    if(vanne_internal_status == EV_OPENED)
        return 1;
    return 0;
}

uint8_t vanne_step_close(uint16_t d)
{
    uint16_t steps = d/(d/101+1);
    uint16_t k;
    uint8_t ret;
    for(k=0;k<d;k+=steps)
    {
        if(k+steps<=d)
            ret = vanne_internal_step_close(steps);
        else
            ret = vanne_internal_step_close(d-k);
        if(ret)
            return ret;
    }
    return ret;
}

uint8_t vanne_step_open(uint16_t d)
{
    uint16_t steps = d/(d/101+1);
    uint16_t k;
    uint8_t ret;
    for(k=0;k<d;k+=steps)
    {
        if(k+steps<=d)
            ret = vanne_internal_step_open(steps);
        else
            ret = vanne_internal_step_open(d-k);
        if(ret)
            return ret;
    }
    return ret;
}

void vanne_close()
{
    uint16_t k;
    for(k=0;k<1000;k++)
        if(vanne_internal_step_close(10))
            break;
    vanne_internal_status = EV_CLOSED;
}

void vanne_open()
{
    uint16_t k;
    for(k=0;k<1000;k++)
        if(vanne_internal_step_open(10))
            break;
    vanne_internal_status = EV_OPENED;
}

void vanne_vidange()
{
    uint16_t kclose;
    uint16_t kopen;
    vanne_close();
    for(kopen=0;kopen<1000;kopen++)
        if(vanne_internal_step_open(10))
            break;
    for(kclose=0;kclose<1000;kclose++)
        if(vanne_internal_step_close(10))
            break;
    uint16_t kmin = (kopen<kclose)?kopen:kclose;
    uint16_t k2=0;
    for(k2=0;k2<kmin/2;k2++)
        if(vanne_internal_step_open(10))
            break;
}
///[[[end]]]

void vanne_callback_open()
{
    led_alert.open = 4;
}

void vanne_callback_close()
{
    led_alert.close = 4;
}