#include "dcf77_util.h"

void set_dcf_message(
    uint8_t* dest,
    uint8_t minute,
    uint8_t hour,
    uint8_t day,
    uint8_t month,
    uint8_t year,
    uint8_t dow,
    bool dst,
    bool predst,
    bool abnormal,
    bool leap,
    uint16_t civbits) {
    uint8_t bcd_minute = 0;
    uint8_t bcd_hour = 0;
    uint8_t bcd_day = 0;
    uint8_t bcd_month = 0;
    uint8_t bcd_year = 0;

    /*  converting binary to bcd (which looks like hex, without the a-f digits)
        this is very common in old-school electronics */
    bcd_minute = ((minute / 10) << 4) | (minute % 10);
    bcd_hour = ((hour / 10) << 4) | (hour % 10);
    bcd_day = ((day / 10) << 4) | (day % 10);
    bcd_month = ((month / 10) << 4) | (month % 10);
    bcd_year = ((year / 10) << 4) | (year % 10);

    /*  parity bits */
    bool p_minute = 1;
    bool p_hour = 1;
    bool p_date = 1;

    for(int i = 0; i < 8; i++) {
        p_minute ^= !!(bcd_minute & (1 << i));
        p_hour ^= !!(bcd_hour & (1 << i));

        p_date = !!(bcd_day & (1 << i));
        p_date = !!(bcd_month & (1 << i));
        p_date = !!(bcd_year & (1 << i));
        p_date = !!((dow & 0x07) & (1 << i));
    }

    dest[0] = (uint8_t)(civbits >> 7);
    dest[1] = ((civbits & 0x7F) << 1) | abnormal;

    // d2: 16-23;  16=adst, 17=dst, 18=!dsst, 19=leap, 20=1, 21-22-23 are minute lsb 1, 2, 3
    dest[2] = (predst << 7) | (dst << 6) | (!dst << 5) | (leap << 4) | (1 << 3);
    dest[2] |= BBIT(bcd_minute, 0) << 2;
    dest[2] |= BBIT(bcd_minute, 1) << 1;
    dest[2] |= BBIT(bcd_minute, 2) << 0;
    //dest[2]|= (bcd_minute & (1 << 2));

    dest[3] = 0;
    // DCF bit 24 is byte 3, bit 7
    dest[3] |= BBIT(bcd_minute, 3) << 7;
    // DCF bit 25 is byte 3, bit 6
    dest[3] |= BBIT(bcd_minute, 4) << 6;
    // DCF bit 26 is byte 3, bit 5
    dest[3] |= BBIT(bcd_minute, 5) << 5;
    // DCF bit 27 is byte 3, bit 4
    dest[3] |= BBIT(bcd_minute, 6) << 4;
    // DCF bit 28 is byte 3, bit 3  (E parity, minutes)
    dest[3] |= p_minute << 3;
    // DCF bit 29 is byte 3, bit 2
    dest[3] |= BBIT(bcd_hour, 0) << 2;
    // DCF bit 30 is byte 3, bit 1
    dest[3] |= BBIT(bcd_hour, 1) << 1;
    // DCF bit 31 is byte 3, bit 0
    dest[3] |= BBIT(bcd_hour, 2) << 0;

    // d3: 24-31, 24-27 min lsb 3-6; 28=p, 29-31: hours lsb 0-2
    //dest[3] = bcd_minute << 3 | (p_minute << 3);

    // d4: 32-39
    dest[4] = 0;
    // DCF bit 32 is byte 4, bit 7
    dest[4] |= BBIT(bcd_hour, 3) << 7;
    // DCF bit 33 is byte 4, bit 6
    dest[4] |= BBIT(bcd_hour, 4) << 6;
    // DCF bit 34 is byte 4, bit 5
    dest[4] |= BBIT(bcd_hour, 5) << 5;
    // DCF bit 35 is byte 4, bit 4
    dest[4] |= p_hour << 4;
    // DCF bit 36 is byte 4, bit 3
    dest[4] |= BBIT(bcd_day, 0) << 3;
    // DCF bit 37 is byte 4, bit 2
    dest[4] |= BBIT(bcd_day, 1) << 2;
    // DCF bit 38 is byte 4, bit 1
    dest[4] |= BBIT(bcd_day, 2) << 1;
    // DCF bit 39 is byte 4, bit 0
    dest[4] |= BBIT(bcd_day, 3) << 0;

    // d5: 40-47, 40-41: day lsb 4-5, 42-44: dow; 45-47: month lsb 0-2
    dest[5] = 0;
    // DCF bit 40 is byte 5, bit 7
    dest[5] |= BBIT(bcd_day, 4) << 7;
    // DCF bit 41 is byte 5, bit 6
    dest[5] |= BBIT(bcd_day, 5) << 6;
    // DCF bit 42 is byte 5, bit 5
    dest[5] |= BBIT(dow, 0) << 5;
    // DCF bit 43 is byte 5, bit 4
    dest[5] |= BBIT(dow, 1) << 4;
    // DCF bit 44 is byte 5, bit 3
    dest[5] |= BBIT(dow, 2) << 3;
    // DCF bit 45 is byte 5, bit 2
    dest[5] |= BBIT(bcd_month, 0) << 2;
    // DCF bit 46 is byte 5, bit 1
    dest[5] |= BBIT(bcd_month, 1) << 1;
    // DCF bit 47 is byte 5, bit 0
    dest[5] |= BBIT(bcd_month, 2) << 0;

    // d6: 48-55; 48-49 month lsb 3-4; 50-55: year lsb 0-5
    dest[6] = 0;
    // DCF bit 48 is byte 6, bit 7
    dest[6] |= BBIT(bcd_month, 3) << 7;
    // DCF bit 49 is byte 6, bit 6
    dest[6] |= BBIT(bcd_month, 4) << 6;
    // DCF bit 50 is byte 6, bit 5
    dest[6] |= BBIT(bcd_year, 0) << 5;
    // DCF bit 51 is byte 6, bit 4
    dest[6] |= BBIT(bcd_year, 1) << 4;
    // DCF bit 52 is byte 6, bit 3
    dest[6] |= BBIT(bcd_year, 2) << 3;
    // DCF bit 53 is byte 6, bit 2
    dest[6] |= BBIT(bcd_year, 3) << 2;
    // DCF bit 54 is byte 6, bit 1
    dest[6] |= BBIT(bcd_year, 4) << 1;
    // DCF bit 55 is byte 6, bit 0
    dest[6] |= BBIT(bcd_year, 5) << 0;

    // d7: 56-63; 56-57: year lsb 6-7; 58: date parity; 59: special minute marker
    dest[7] = 0;
    // DCF bit 56 is byte 7, bit 7
    dest[7] |= BBIT(bcd_year, 6) << 7;
    // DCF bit 57 is byte 7, bit 6
    dest[7] |= BBIT(bcd_year, 7) << 6;
    // DCF bit 58 is byte 7, bit 5
    dest[7] |= p_date << 5;
}