int
au_check_header_valid(int idx, long nbytes)
{
	image_header_t *hdr;
	unsigned long checksum;
	unsigned char buf[4];

	hdr = (image_header_t *)LOAD_ADDR;
#if defined(CONFIG_FIT)
	if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) {
		puts ("Non legacy image format not supported\n");
		return -1;
	}
#endif

	/* check the easy ones first */
#undef CHECK_VALID_DEBUG
#ifdef CHECK_VALID_DEBUG
	printf("magic %#x %#x ", image_get_magic (hdr), IH_MAGIC);
	printf("arch %#x %#x ", image_get_arch (hdr), IH_ARCH_ARM);
	printf("size %#x %#lx ", image_get_data_size (hdr), nbytes);
	printf("type %#x %#x ", image_get_type (hdr), IH_TYPE_KERNEL);
#endif
	if (nbytes < image_get_header_size ()) {
		printf ("Image %s bad header SIZE\n", aufile[idx]);
		return -1;
	}
	if (!image_check_magic (hdr) || !image_check_arch (hdr, IH_ARCH_ARM)) {
		printf ("Image %s bad MAGIC or ARCH\n", aufile[idx]);
		return -1;
	}
	/* check the hdr CRC */
	if (!image_check_hcrc (hdr)) {
		printf ("Image %s bad header checksum\n", aufile[idx]);
		return -1;
	}
	/* check the type - could do this all in one gigantic if() */
	if ((idx == IDX_FIRMWARE) &&
		!image_check_type (hdr, IH_TYPE_FIRMWARE)) {
		printf ("Image %s wrong type\n", aufile[idx]);
		return -1;
	}
	if ((idx == IDX_KERNEL) && !image_check_type (hdr, IH_TYPE_KERNEL)) {
		printf ("Image %s wrong type\n", aufile[idx]);
		return -1;
	}
	if ((idx == IDX_DISK) && !image_check_type (hdr, IH_TYPE_FILESYSTEM)) {
		printf ("Image %s wrong type\n", aufile[idx]);
		return -1;
	}
	if ((idx == IDX_APP) && !image_check_type (hdr, IH_TYPE_RAMDISK)
		&& !image_check_type (hdr, IH_TYPE_FILESYSTEM)) {
		printf ("Image %s wrong type\n", aufile[idx]);
		return -1;
	}
	if ((idx == IDX_PREPARE || idx == IDX_PREINST || idx == IDX_POSTINST)
		&& !image_check_type (hdr, IH_TYPE_SCRIPT)) {
		printf ("Image %s wrong type\n", aufile[idx]);
		return -1;
	}
	/* special case for prepare.img */
	if (idx == IDX_PREPARE)
		return 0;
	/* recycle checksum */
	checksum = image_get_data_size (hdr);
	/* for kernel and app the image header must also fit into flash */
	if ((idx != IDX_DISK) && (idx != IDX_FIRMWARE))
		checksum += image_get_header_size ();
	/* check the size does not exceed space in flash. HUSH scripts */
	/* all have ausize[] set to 0 */
	if ((ausize[idx] != 0) && (ausize[idx] < checksum)) {
		printf ("Image %s is bigger than FLASH\n", aufile[idx]);
		return -1;
	}
	/* check the time stamp from the EEPROM */
	/* read it in */
	i2c_read_multiple(0x54, auee_off[idx].time, 1, buf, sizeof(buf));
#ifdef CHECK_VALID_DEBUG
	printf ("buf[0] %#x buf[1] %#x buf[2] %#x buf[3] %#x "
		"as int %#x time %#x\n",
		buf[0], buf[1], buf[2], buf[3],
		*((unsigned int *)buf), image_get_time (hdr));
#endif
	/* check it */
	if (*((unsigned int *)buf) >= image_get_time (hdr)) {
		printf ("Image %s is too old\n", aufile[idx]);
		return -1;
	}

	return 0;
}
int main ( void )
{
    /* Initialize all MPLAB Harmony modules, including application(s). */
    SYS_Initialize ( NULL );

    __builtin_disable_interrupts();

    // set the CP0 CONFIG register to indicate that kseg0 is cacheable (0x3)
    __builtin_mtc0(_CP0_CONFIG, _CP0_CONFIG_SELECT, 0xa4210583);

    // 0 data RAM access wait states
    BMXCONbits.BMXWSDRM = 0x0;

    // enable multi vector interrupts
    INTCONbits.MVEC = 0x1;

    // disable JTAG to get pins back
    DDPCONbits.JTAGEN = 0;
    
    // initialize I2C
    initI2C2();
    
    // initialize IMU
    initIMU();
    
    // initialize SPI, LCD
//    SPI1_init();
//    LCD_init();
    
    __builtin_enable_interrupts();
    
//    LCD_clearScreen(BLACK);   
//    char message[MAX_LENGTH];  
    unsigned char data[14];
//    float accX, accY;
    _CP0_SET_COUNT(0);
    while ( true )
    {
        if (_CP0_GET_COUNT() > 480000) {    // 50 Hz     
            i2c_read_multiple(IMU_ADDRESS, OUT_TEMP_L, data, 14);
            temp_raw = data[1] << 8 | data[0];
            gyroX_raw = data[3] << 8 | data[2];
            gyroY_raw = data[5] << 8 | data[4];
            gyroZ_raw = data[7] << 8 | data[6];
            accX_raw = data[9] << 8 | data[8];
            accY_raw = data[11] << 8 | data[10];
            accZ_raw = data[13] << 8 | data[12];
            
//            accX = accX_raw * 2.0 / 32768; // accel in g
//            accY = accY_raw * 2.0 / 32768; // accel in g
//            accZ = accZ_raw * 2.0 / 32768; // accel in g
            
//            sprintf(message, "temp raw: %x    ", temp_raw);
//            LCD_drawString(10, 10, message, WHITE);
//            
//            sprintf(message, "accX: %f g    ", accX);
//            LCD_drawString(10, 20, message, WHITE);
//            
//            sprintf(message, "accY: %f g    ", accY);
//            LCD_drawString(10, 30, message, WHITE);
//            
//            sprintf(message, "accZ: %f g    ", accZ);
//            LCD_drawString(10, 40, message, WHITE);
//            
//            sprintf(message, "gyroX raw: %i    ", gyroX_raw);
//            LCD_drawString(10, 50, message, WHITE);
//            
//            sprintf(message, "gyroY raw: %i    ", gyroY_raw);
//            LCD_drawString(10, 60, message, WHITE);
//            
//            sprintf(message, "gyroZ raw: %i    ", gyroZ_raw);
//            LCD_drawString(10, 70, message, WHITE);
            
            _CP0_SET_COUNT(0);
        }
        
        /* Maintain state machines of all polled MPLAB Harmony modules. */
        SYS_Tasks ( );

    }

    /* Execution should not come here during normal operation */

    return ( EXIT_FAILURE );
}