#include <stdint.h>
#include <util/crc16.h>
#include <avr/pgmspace.h>
#include "crc.h"
#include "junk.h"
#include "main.h"


#define pgm_get_far_address(var) ({ \
    uint_farptr_t tmp; \
    \
    __asm__ __volatile__( \
    \
    "ldi %A0, lo8(%1)" "\n\t" \
    "ldi %B0, hi8(%1)" "\n\t" \
    "ldi %C0, hh8(%1)" "\n\t" \
    "clr %D0" "\n\t" \
    : \
    "=d" (tmp) \
    : \
    "p" (&(var)) \
    ); \
    tmp; \
    })

static uint16_t calculate_flash_crc_static()
{
  uint16_t crc = 0xFFFF;

  for (uint32_t i = 0; i <APP_END_ADR; i++)
  {
    crc = _crc16_update(crc, pgm_read_byte_far(i));  
  }
  return crc;
}

/*
static uint16_t calculate_flash_crc(uint32_t start, uint16_t count)
{
  uint32_t i;
  uint16_t crc = 0xFFFF;

  for ( i = start; count > 0; i++, count--)
  {
    crc = _crc16_update(crc, pgm_read_byte_far(i));  
  }
  return crc;
}

static uint16_t calculate_flash_crc_pure_c(uint32_t start, uint16_t count)
{
    uint32_t i;
    uint8_t j, data;
    uint16_t crc = 0xFFFF;

    for ( i = start; count > 0; i++, count--) {
        data = pgm_read_byte_far(i);
    	crc ^= data;
	    for (j = 0; j < 8; j++) {
	        if (crc & 1)
		        crc = (crc >> 1) ^ 0xA001;
	        else
		        crc = (crc >> 1);
	    }
    }  
    return crc;
}
*/

int main(void) {
    volatile uint16_t crc1;
    
//    crc1 = calculate_flash_crc(pgm_get_far_address(a), 16);
//    crc1 = calculate_flash_crc_pure_c(pgm_get_far_address(a), 16);
    crc1 = calculate_flash_crc_static();
    crc1 = calculate_crc_asm();
}