/*
	MGPIODAC.C

	BL14xx/MicroG or BL15xx/MicroG2

	Simple DAC using bit 2 (PA2, H3-4) of the PIODA port. The DAC value is
	generated by proportioning the duty cycle of the output active time to
	the requested dac value.

	This DAC approximates 10 bit across 5 volts. Watchout for interrupt
	latency which could affect the duty cycle of the output bit.

	If the MicroG Prototyping Board is used, connect PA2 to TP5. DAC output
	is available on TP9.
*/

void PioDac(float dacvalue);

main()
{
int i;
float testdac;

	testdac = 0.00;

	while(1)
	{
		hitwd();
		runwatch();
		PioDac(testdac);
		testdac++;
		if(testdac > 5.00) testdac = 0.00;
		for(i=0;i<10000;i++);
	}
}

// PioDac(float dacvalue)
// Set up timer0 to generate crude DAC output out of bit 2 of PIODA.
char hi_hi, hi_lo;
char lo_hi, lo_lo;
char bit_hi_lo;
void PioDac(float dacvalue)
{
		int i;

		resPIOCA(0x04);                  // set bit 2 to output
		resPIODA(0x04);                  // initialize to zero
		
		if( dacvalue <= 0.0)
			i = 1;
		else if (dacvalue >= 5.00)
			i = 1023;
		else
			i = (int)(204.8 * dacvalue);   // get the load value
		
		hi_hi = (i >> 8) & 0xff;
		hi_lo = i & 0xff;

		i = 1024 - i;

		lo_hi = (i >> 8) & 0xff;
		lo_lo = i & 0xff;

		DI();
		bit_hi_lo = 1;
		outport(TCR, inport(TCR) & '\B11101110');    // inhibit TIMER0 interrupt
		outport(TMDR0L, hi_lo);
		outport(TMDR0H, hi_hi);
		outport(TCR, inport(TCR) | '\B00010001');
		outport(PIODA, inport(PIODA) | '\B00000100');
		EI();
}

#INT_VEC PRT0_VEC dac_pio
// timer0 interrupt service routine, generate pulses that are proportional
// to the on time of the dac value.
#asm nodebug
dac_pio::
			push  af
			in0   a, (TCR)
			in0   a, (TMDR0L)

			ld    a, (bit_hi_lo)
			cp    1
			jr    nz, out_high

out_low:
			ld    a, (lo_hi)
			out0  (TMDR0H), a
			ld    a, (lo_lo)
			out0  (TMDR0L), a
			in0   a, (PIODA)
			and   11111011b
			out0  (PIODA), a
			ld    a, 0
			jr    merge       

out_high:
			ld    a, (hi_hi)
			out0  (TMDR0H), a
			ld    a, (hi_lo)
			out0  (TMDR0L), a
			in0   a, (PIODA)
			or    00000100b
			out0  (PIODA), a
			ld    a, 1
merge:
			ld    (bit_hi_lo), a
			pop   af
			ei
			ret
#endasm