
#include "bl_tools.h"

#pragma SET_CODE_SECTION(".bl_text")

#define BL_CRC_32_POLINOM_VALUE 0x04C11DB7
#define BL_CRC_16_POLINOM_VALUE 0x8005


//*******************************************************************************************************
uint32_t bl_getCRC32(uint32_t* pData, uint32_t n32BitValues)
{
    //Diese Funktion berechnet die CRC-32 Summe, ohne die Bits der Daten zu drehen.
    //Dieses Drehen heißt "reflected"
    //Die hier implementierte Variante wird auch CRC-32/BZIP2 genannt
    //Eine sehr gute Erklärung dieser Funktion (die es auf vielen Webseiten so gibt)
    //ist unter http://www.sunshine2k.de/articles/coding/crc/understanding_crc.html zu finden
    //Unter http://www.sunshine2k.de/coding/javascript/crc/crc_js.html kann man Beispieldaten eingeben

    uint32_t WorkRegister = 0xFFFFFFFF;
    while (n32BitValues > 0)
    {
        WorkRegister ^= *pData;
        for (int i=0; i<32; i++)
        {
            if ((WorkRegister & 0x80000000) != 0)
                WorkRegister = (WorkRegister << 1) ^ BL_CRC_32_POLINOM_VALUE;
            else
                WorkRegister <<= 1;
        }
        n32BitValues--;
        pData++;
    }

    return ~WorkRegister;
}

//*******************************************************************************************************
uint16_t bl_getCRC16(uint8_t* pData, uint32_t n16BitValues)
{
    //Diese Funktion berechnet die CRC-16 Summe, ohne die Bits der Daten zu drehen.
    //Dieses Drehen heißt "reflected"
    //Die hier implementierte Variante wird auch CRC-16/BUYPASS genannt
    //Eine sehr gute Erklärung dieser Funktion (die es auf vielen Webseiten so gibt)
    //ist unter http://www.sunshine2k.de/articles/coding/crc/understanding_crc.html zu finden
    //Unter http://www.sunshine2k.de/coding/javascript/crc/crc_js.html kann man Beispieldaten eingeben

    uint16_t WorkRegister = 0;
    while (n16BitValues > 0)
    {
        //Für die Logik müssen die Daten als 16-Bit Werte im MSB Format vorliegen.
        //Der Prozessor arbeitet aber generell im LSB Format. Daher geht ein einfaches MemCopy nicht
        uint16_t hData = *pData;
        pData++;
        hData = (hData << 8) + *pData;
        pData++;
        WorkRegister ^= hData;
        for (int i=0; i<16; i++)
        {
            if ((WorkRegister & 0x8000) != 0)
                WorkRegister = (WorkRegister << 1) ^ BL_CRC_16_POLINOM_VALUE;
            else
                WorkRegister <<= 1;
        }
        n16BitValues--;
    }

    return WorkRegister;
}

//*******************************************************************************************************
void bl_getCRC32_init(uint32_t* pWorkRegister)
{
    *pWorkRegister = 0xFFFFFFFF;
}

//*******************************************************************************************************
void bl_getCRC32_aWord(uint32_t* pWorkRegister, uint32_t aWord)
{
    *pWorkRegister ^= aWord;
    for (int i=0; i<32; i++)
    {
        if ((*pWorkRegister & 0x80000000) != 0)
            *pWorkRegister = (*pWorkRegister << 1) ^ BL_CRC_32_POLINOM_VALUE;
        else
            *pWorkRegister <<= 1;
    }
}

//*******************************************************************************************************
void bl_getCRC32_done(uint32_t* pWorkRegister)
{
    *pWorkRegister = ~*pWorkRegister;
}

///*
//
//\brief     Debug stack pointer.
//\param sp  Stack pointer.
//Provide a view into the CPU state from the provided stack pointer.
//*/
//static void
//debugHardfault(uint32_t sp)
//{
//volatile uint32_t r0;  /< R0 register /
//volatile uint32_t r1;  /< R1 register /
//volatile uint32_t r2;  /< R2 register /
//volatile uint32_t r3;  /< R3 register /
//volatile uint32_t r12; /< R12 register /
//volatile uint32_t lr;  /< LR register /
//volatile uint32_t pc;  /< PC register /
//volatile uint32_t psr; /*< PSR register */
//(void)(r0  = sp[0]);
//(void)(r1  = sp[1]);
//(void)(r2  = sp[2]);
//(void)(r3  = sp[3]);
//(void)(r12 = sp[4]);
//(void)(lr  = sp[5]);
//(void)(pc  = sp[6]);
//(void)(psr = sp[7]);
//
///* Enter an infinite loop. */
//for(;;) { /* hang */ }
//}
//
///*---------------------------------------------------------------------------/
///
//
//\brief  CPU Fault ISR.
//This is the code that gets called when the processor receives a fault
//interrupt. Setup a call to debugStackPointer with the current stack pointer.
//The stack pointer in this case would be the CPU state which caused the CPU
//fault.
//*/
//static void
//faultISR(void)
//{
//asm volatile
//(
//"tst lr, #4        \n"
//"ite eq            \n"
//"mrseq r0, msp     \n"
//"mrsne r0, psp     \n"
//"bx %0             \n"
//: / output /
//: / input */
//"r"(debugHardfault)
//);
//}
#pragma SET_CODE_SECTION()



