text: /*
  Copyright (c) 2014, Pure Engineering LLC
  All rights reserved.
  
  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:
  
  * Redistributions of source code must retain the above copyright notice, this
    list of conditions and the following disclaimer.
  
  * Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.
  
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
  
  #include <stdint.h>
  #include <unistd.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <getopt.h>
  #include <fcntl.h>
  #include <sys/ioctl.h>
  #include <linux/types.h>
  #include <linux/spi/spidev.h>
  
  #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
  
  static void pabort(const char *s)
  {
  	perror(s);
  	abort();
  }
  
  static const char *device = "/dev/spidev0.0";
  static uint8_t mode;
  static uint8_t bits = 8;
  static uint32_t speed = 16000000;
  static uint16_t delay;
  
  #define VOSPI_FRAME_SIZE (164)
  uint8_t lepton_frame_packet[VOSPI_FRAME_SIZE];
  static int lepton_image[80][80];
  
  static void save_pgm_file(void)
  {
  	int i;
  	int j;
  
  	FILE *f = fopen("image.pgm", "w");
  	if (f == NULL)
  	{
  		printf("Error opening file!\n");
  		exit(1);
  	}
  
  	fprintf(f,"P2\n80 60\n255\n");
  	for(i=0;i<60;i++)
  	{
  		for(j=0;j<80;j++)
  		{
  			fprintf(f,"%d ", lepton_image[i][j]);
  		}
  		printf("\n");
  	}
  	printf("\n\n");
  
  	fclose(f);
  }
  
  static void print_image(void)
  {
  	int i;
  	int j;
  
  	printf("P2\n80\n60\n255\n");
  	for(i=0;i<60;i++)
  	{
  		for(j=0;j<80;j++)
  		{
  			printf("%d ", lepton_image[i][j]);
  		}
  		printf("\n");
  	}
  	printf("\n\n");
  
  
  }
  
  static void transfer(int fd)
  {
  	int ret;
  	int i;
  	int j;
  	int frame_number;
  	uint8_t tx[VOSPI_FRAME_SIZE] = {0, };
  	struct spi_ioc_transfer tr = {
  		.tx_buf = (unsigned long)tx,
  		.rx_buf = (unsigned long)lepton_frame_packet,
  		.len = VOSPI_FRAME_SIZE,
  		.delay_usecs = delay,
  		.speed_hz = speed,
  		.bits_per_word = bits,
  	};
  
  	ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
  	if (ret < 1)
  		pabort("can't send spi message");
  
  	if(((lepton_frame_packet[0]&0xf) != 0x0f))
  	{
  		frame_number = lepton_frame_packet[1];
  
  		if(frame_number < 60 )
  		{
  			for(i=0;i<80;i++)
  			{
  				lepton_image[frame_number][i] = (lepton_frame_packet[2*i+4] << 8 | lepton_frame_packet[2*i+5]);
  			}
  		}
  	}
  
  	if(frame_number == 59)
  	{
  		print_image();
  	}
  }
  
  int main(int argc, char *argv[])
  {
  	int ret = 0;
  	int fd;
  	int i;
  
  
  	fd = open(device, O_RDWR);
  	if (fd < 0)
  	{
  		pabort("can't open device");
  	}
  
  	ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
  	if (ret == -1)
  	{
  		pabort("can't set spi mode");
  	}
  
  	ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
  	if (ret == -1)
  	{
  		pabort("can't get spi mode");
  	}
  
  	ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
  	if (ret == -1)
  	{
  		pabort("can't set bits per word");
  	}
  
  	ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
  	if (ret == -1)
  	{
  		pabort("can't get bits per word");
  	}
  
  	ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
  	if (ret == -1)
  	{
  		pabort("can't set max speed hz");
  	}
  
  	ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
  	if (ret == -1)
  	{
  		pabort("can't get max speed hz");
  	}
  
  	printf("spi mode: %d\n", mode);
  	printf("bits per word: %d\n", bits);
  	printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
  
  	for(i=0;i<5000;i++)
  	{
  		transfer(fd);
  	}
  
  	close(fd);
  
  	save_pgm_file();
  
  	return ret;
  }
  