/*
  DisplayEprom

  Dit tooltje is ontworpen om een eprom voor de SpanningsMeter
  te vullen met de nodige bytes.
  Bij het starten kan het hoogste cijfer meegegeven worden
  in de vorm van een float.
  Gebeurt dit niet, dan zal het programma daar zelf om vragen.

  Pros 2002
*/


#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <math.h>


#define DEBUG_

/*
  De definities voor een display.
  Voor de elementen a, b, c, d ,e ,f en g
  worden bits 0 ... 6 gebruikt.
  Voor de decimale punt doet bit 7 dienst.
*/
#define A 0x02
#define B 0x40
#define C 0x20
#define D 0x10
#define E 0x08
#define F 0x04
#define G 0x80
#define DP 0x01


unsigned int led[] = {A | B | C | D | E | F,
		      B | C,
		      A | B | G | E | D,
		      A | B | C | D | G,
		      B | C | F | G,
		      A | F | G | C | D,
		      A | F | G | C | D | E,
		      A | B | C,
		      A | B | C | D | E | F | G,
		      A | B | C | D | F | G
};

char *d1, *d2, *d3, *d4;
char *p;
char tmp[100];
double maxvalue, step, v;
int cnt, dp, a, b, c, fd, x;
unsigned char eprom[16384];
unsigned int mx;


int main(int argc, char *argv[])
{
    if (argc == 2) {
	maxvalue = atof(argv[1]);
	/*
	  We willen weten hoeveel cijfers er voor de komma zijn.
	  De opgegeven float wordt intern immers als een integer
	  verwerkt (12.34 = 1234; 5.2 = 5200; 3456.7 = 3456; 234567.8 = 2345).
	  Daarom zoeken we uit, waar zich de decimale punt bevindt.
	*/
	dp = 0;
	p = argv[1];
	while ((*p != '.') && (*p != '\n') && (*p != 0)) {
	    dp++;
	    p++;
	}
    } else {
	printf("Geef de maximale display-waarde op, a.u.b.\n  : ");
	fgets(tmp, sizeof(tmp), stdin);
	maxvalue = atof(tmp);
	dp = 0;
	p = tmp;
	while ((*p != '.') && (*p != '\n') && (*p != 0)) {
	    dp++;
	    p++;
	}
    }

    /* Nu de opgegeven waarde omtoveren in een integer */
    if (dp == 4) {
	/* niets na de komma */
	mx = maxvalue;
    } else if (dp < 4) {
	a = 4 - dp;
	mx = maxvalue * pow(10.0, (double) a);
    } else {
	/* de opgegeven komma is onbruikbaar */
	a = dp - 4;
	mx = maxvalue / pow(10.0, (double) a);
	dp = 4;
    }

    /*
      Er zijn 4096 waarden beschikbaar, gaande van 0000 tot mx (4 cijfers).
      Even het verschil tussen 2 stappen uitrekenen...
    */
    step = (double) mx / 4096.0;
    
#ifdef DEBUG
    printf("Max value = %f\n", maxvalue);
    printf("%d cijfers voor de komma\n", dp);
    printf("Decimaal: %d\n", mx);
    printf("Step = %f\n", step);
#endif

    /*
      Nu weten we alles dat we weten moeten,
      en kunnen we aan de slag.

      Om te beginnen plaatsen we 4 pointers elk aan het begin
      van het datablok van 1 display
    */
    d1 = eprom;
    d2 = eprom + 4096;
    d3 = eprom + 8192;
    d4 = eprom + 12288;
    /* v is de waarde die in 4096 stappen van 0 tot max gaat */
    v = 0.0;
    for (b = 0; b < 4096; b++) {
	/*
	  Een getal als bv 1357 omtoveren naar 4 digits: 1, 3, 5 en 7

	  1357 / 1000 = 1
	  1357 - (1 * 1000) = 357
	  357 / 100 = 3
	  357 - (3 * 100) = 57
	  57 / 10 = 5
	  57 - (5 * 10) = 7
	*/
	x = v;
#ifdef DEBUG
	c = (int) x / 1000;
	*d1 = c + '0';
	d1++;
	x -= (c * 1000);
	c = (int) x / 100;
	*d2 = c + '0';
	d2++;
	x -= (c * 100);
	c = (int) x / 10;
	*d3 = c + '0';
	d3++;
	x -= (c * 10);
	c = (int) x;
	*d4 = c + '0';
	d4++;
#else
	c = (int) x / 1000;
	if (dp == 1) {
	    *d1 = led[c] | DP;
	} else {
	*d1 = led[c];
	}
	d1++;
	x -= (c * 1000);
	c = (int) x / 100;
	if (dp == 2) {
	    *d2 = led[c] | DP;
	} else {
	*d2 = led[c];
	}
	d2++;
	x -= (c * 100);
	c = (int) x / 10;
	if (dp == 3) {
	    *d3 = led[c] | DP;
	} else {
	*d3 = led[c];
	}
	d3++;
	x -= (c * 10);
	c = (int) x;
	*d4 = led[c];
	d4++;
#endif
	v += step;
    }

    /* Nu alles wegschrijven... */
    fd = open("eprom", O_WRONLY | O_CREAT | O_TRUNC);
    if (fd != -1) {
	write(fd, eprom, 16384);
	close(fd);
    }
}