view lcdtest/showppm.c @ 111:5bfb5a7262c1

fc-simtool: pb-update command implemented
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 26 Jan 2021 03:22:26 +0000
parents 1d8c499711f1
children
line wrap: on
line source

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>

char *ppm_filename;
FILE *ppmfile;
int ppm_is_ascii;		/* P3 format instead of P6 */

/*
 * This function reads one ASCII-encoded integer from a PPM file.
 * It handles the white space and comment rules of the PPM format.
 */
static int
ppm_get_ascii_number()
{
	int accum, c;

	do {
		c = getc(ppmfile);
		if (c < 0) {
badeof:			fprintf(stderr, "%s: unexpected EOF\n", ppm_filename);
			return(-1);
		}
		if (c == '#') {
			do
				c = getc(ppmfile);
			while (c >= 0 && c != '\n');
			if (c != '\n')
				goto badeof;
		}
	} while (isspace(c));
	if (!isdigit(c)) {
		fprintf(stderr,
			"%s: unexpected data where a number was expected\n",
			ppm_filename);
		return(-1);
	}
	for (accum = c - '0'; ; ) {
		c = getc(ppmfile);
		if (c < 0 || isspace(c))
			break;
		if (!isdigit(c)) {
			fprintf(stderr,
				"%s: bad character in the middle of a number\n",
				ppm_filename);
			return(-1);
		}
		accum = accum * 10 + c - '0';
	}
	return accum;
}

/*
 * This function reads and parses the PPM header of our input file.
 */
static int
ppm_read_header()
{
	int magic1, magic2;
	int rd;

	magic1 = getc(ppmfile);
	magic2 = getc(ppmfile);
	if (magic1 == 'P' && magic2 == '3')
		ppm_is_ascii = 1;
	else if (magic1 == 'P' && magic2 == '6')
		ppm_is_ascii = 0;
	else {
		fprintf(stderr, "%s: P3 or P6 format expected\n", ppm_filename);
		return(-1);
	}
	rd = ppm_get_ascii_number();
	if (rd < 0)
		return(-1);
	if (rd != 176) {
		fprintf(stderr, "%s: width is not 176\n", ppm_filename);
		return(-1);
	}
	rd = ppm_get_ascii_number();
	if (rd < 0)
		return(-1);
	if (rd != 220) {
		fprintf(stderr, "%s: height is not 220\n", ppm_filename);
		return(-1);
	}
	rd = ppm_get_ascii_number();
	if (rd < 0)
		return(-1);
	if (rd != 255) {
		fprintf(stderr, "%s: maxval is not 255\n", ppm_filename);
		return(-1);
	}
	return(0);
}

/*
 * This function reads a single R, G or B value from a PPM file.
 */
static int
ppm_get_pixval()
{
	int c;

	if (ppm_is_ascii)
		return ppm_get_ascii_number();
	c = getc(ppmfile);
	if (c < 0) {
		fprintf(stderr, "%s: EOF while reading binary pixel data\n",
			ppm_filename);
		return(-1);
	}
	return c;
}

static int
ppm_get_rgb()
{
	int r, g, b;

	r = ppm_get_pixval();
	if (r < 0)
		return(-1);
	g = ppm_get_pixval();
	if (g < 0)
		return(-1);
	b = ppm_get_pixval();
	if (b < 0)
		return(-1);
	/* convert to 5:6:5 */
	r >>= 3;
	g >>= 2;
	b >>= 3;
	return (r << 11) | (g << 5) | b;
}

cmd_show(argc, argv)
	char **argv;
{
	int rc;
	unsigned n;
	u_char ftbuf[176*220*6+3], *dp;

	ppm_filename = argv[1];
	ppmfile = fopen(ppm_filename, "r");
	if (!ppmfile) {
		perror(ppm_filename);
		return(-1);
	}
	rc = ppm_read_header();
	if (rc < 0) {
		fclose(ppmfile);
		return(-1);
	}
	write_ir(0x20);
	write_dr(0);
	write_ir(0x21);
	write_dr(0);
	write_ir(0x22);
	/* GPIO setup */
	dp = ftbuf;
	*dp++ = 0x82;
	*dp++ = 0x03;
	*dp++ = 0x03;
	for (n = 0; n < 176*220; n++) {
		rc = ppm_get_rgb();
		if (rc < 0) {
			fclose(ppmfile);
			return(-1);
		}
		/* upper byte */
		*dp++ = 0x92;
		*dp++ = 0;	/* dummy addr */
		*dp++ = rc >> 8;
		/* lower byte */
		*dp++ = 0x92;
		*dp++ = 0;	/* dummy addr */
		*dp++ = rc;
	}
	fclose(ppmfile);
	do_ftdi_write(ftbuf, sizeof ftbuf);
	return(0);
}

cmd_cd(argc, argv)
	char **argv;
{
	if (chdir(argv[1]) < 0) {
		perror(argv[1]);
		return(-1);
	}
	return(0);
}