// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <stdint.h>
#include "esp32/rom/crc.h"
#include "sdspi_crc.h"

static const uint8_t crc7_table[256] =
{
	0x00,  0x09,  0x12,  0x1b,  0x24,  0x2d,  0x36,  0x3f,  0x48,  0x41,  0x5a,  0x53,  0x6c,  0x65,  0x7e,  0x77,
	0x19,  0x10,  0x0b,  0x02,  0x3d,  0x34,  0x2f,  0x26,  0x51,  0x58,  0x43,  0x4a,  0x75,  0x7c,  0x67,  0x6e,
	0x32,  0x3b,  0x20,  0x29,  0x16,  0x1f,  0x04,  0x0d,  0x7a,  0x73,  0x68,  0x61,  0x5e,  0x57,  0x4c,  0x45,
	0x2b,  0x22,  0x39,  0x30,  0x0f,  0x06,  0x1d,  0x14,  0x63,  0x6a,  0x71,  0x78,  0x47,  0x4e,  0x55,  0x5c,
	0x64,  0x6d,  0x76,  0x7f,  0x40,  0x49,  0x52,  0x5b,  0x2c,  0x25,  0x3e,  0x37,  0x08,  0x01,  0x1a,  0x13,
	0x7d,  0x74,  0x6f,  0x66,  0x59,  0x50,  0x4b,  0x42,  0x35,  0x3c,  0x27,  0x2e,  0x11,  0x18,  0x03,  0x0a,
	0x56,  0x5f,  0x44,  0x4d,  0x72,  0x7b,  0x60,  0x69,  0x1e,  0x17,  0x0c,  0x05,  0x3a,  0x33,  0x28,  0x21,
	0x4f,  0x46,  0x5d,  0x54,  0x6b,  0x62,  0x79,  0x70,  0x07,  0x0e,  0x15,  0x1c,  0x23,  0x2a,  0x31,  0x38,
	0x41,  0x48,  0x53,  0x5a,  0x65,  0x6c,  0x77,  0x7e,  0x09,  0x00,  0x1b,  0x12,  0x2d,  0x24,  0x3f,  0x36,
	0x58,  0x51,  0x4a,  0x43,  0x7c,  0x75,  0x6e,  0x67,  0x10,  0x19,  0x02,  0x0b,  0x34,  0x3d,  0x26,  0x2f,
	0x73,  0x7a,  0x61,  0x68,  0x57,  0x5e,  0x45,  0x4c,  0x3b,  0x32,  0x29,  0x20,  0x1f,  0x16,  0x0d,  0x04,
	0x6a,  0x63,  0x78,  0x71,  0x4e,  0x47,  0x5c,  0x55,  0x22,  0x2b,  0x30,  0x39,  0x06,  0x0f,  0x14,  0x1d,
	0x25,  0x2c,  0x37,  0x3e,  0x01,  0x08,  0x13,  0x1a,  0x6d,  0x64,  0x7f,  0x76,  0x49,  0x40,  0x5b,  0x52,
	0x3c,  0x35,  0x2e,  0x27,  0x18,  0x11,  0x0a,  0x03,  0x74,  0x7d,  0x66,  0x6f,  0x50,  0x59,  0x42,  0x4b,
	0x17,  0x1e,  0x05,  0x0c,  0x33,  0x3a,  0x21,  0x28,  0x5f,  0x56,  0x4d,  0x44,  0x7b,  0x72,  0x69,  0x60,
	0x0e,  0x07,  0x1c,  0x15,  0x2a,  0x23,  0x38,  0x31,  0x46,  0x4f,  0x54,  0x5d,  0x62,  0x6b,  0x70,  0x79,
};

// returns the CRC-7 for a message of "length" bytes
uint8_t sdspi_crc7(const uint8_t *data, size_t size)
{
    uint8_t result = 0;
    for (size_t i = 0; i < size; ++i) {
        result = crc7_table[(result << 1) ^ data[i]];
    }
    return result;
}

/// Return CRC16 of data, in the on-the-wire format used by SD protocol
uint16_t sdspi_crc16(const uint8_t* data, size_t size)
{
    return __builtin_bswap16(crc16_be(UINT16_MAX, data, size) ^ UINT16_MAX);
}