#include <atmel_start.h>

#include <COAST.h>
#include "checksums.h"

uint16_t __xMR_FN_CALL sysv_checksum(uint8_t *start_addr, uint8_t *end_addr)
{
        uint32_t result = 0;
        uint16_t result16 = 0;
        uint8_t *p = start_addr;
        while (p != end_addr)
                result += *(p++);
        result16 = (result & 0xffff) + ((result & 0xffffffff) >> 16);
        return (result16 & 0xffff) + (result16 >> 16);
}

uint8_t __xMR_FN_CALL crc8_byte(uint8_t n)
{
        uint8_t poly = 0x07; /* x^8 + x^2 + x + 1 */
        uint8_t crc = n;
        for (uint8_t i = 0; i < 8; ++i)
                if (crc & 0x80)
                        crc = ((crc << 1) ^ poly);
                else
                        crc = (crc << 1);
        return crc;
}

static uint8_t crc8_byte_notmr(uint8_t n)
{
        uint8_t poly = 0x07; /* x^8 + x^2 + x + 1 */
        uint8_t crc = n;
        for (uint8_t i = 0; i < 8; ++i)
                if (crc & 0x80)
                        crc = ((crc << 1) ^ poly);
                else
                        crc = (crc << 1);
        return crc;
}

uint8_t __xMR_FN_CALL crc8_bytearray(uint8_t *na, uint8_t len, uint8_t start_val)
{
        uint8_t result = start_val;
        for (uint8_t i = 0; i < len; ++i) {
                result = crc8_byte_notmr(result ^ na[i]);
        }
        return result;
}
