//
// SW for leoprogrammable, this is for my testing of boards
// Copyright (c) 2006 Leo Villareal
// Author: Jesse Lackey, jesse@celestialaudio.com
//

// +DF +LN +T -A +M +Z +Y=9 -E +EW I+="F:\dev\libs_and_binaries\pic_lib"
//

#include <18f4620.h>


//#define DO_ICD
#define DO_DEBUG_SERIAL


// highspeed xtal with 4x pll: "H4"
#fuses H4,NOPROTECT,BROWNOUT,PUT,NOLVP,STVREN,NOCPD,NOCPB,NOEBTRB,NOWRTB,NOWRTC,NOFCMEN,NOIESO,NOLPT1OSC,NOXINST
#ifdef DO_ICD
#device ICD=TRUE
#fuses DEBUG,NOWDT
#else
#fuses NODEBUG
#endif

// 10-bit ADC
#device ADC=10

// don't have ccsc do any direction switching for us
// these are supposed to be before #use rs232 so that code doesn't do switching
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
#use fast_io(E)
	
#use delay (clock= 40000000)
	
#include <ctype.h>
#include <stdlib.h>

// DMX
#use rs232 (BAUD=250000,XMIT=PIN_C6,RCV=PIN_C7,PARITY=N,BITS=9,ERRORS,BRGH1OK,STREAM=DMX)
// debugging
#use rs232 (BAUD=57600,XMIT=PIN_B1,RCV=PIN_B0,PARITY=N,ERRORS, BRGH1OK,DISABLE_INTS,STREAM=DEBUG_SERIAL)


#include "misc.c"

#BYTE PORT_A = 0xF80
#BYTE PORT_B = 0xF81
#BYTE PORT_C = 0xF82
#BYTE PORT_D = 0xF83
#BYTE PORT_E = 0xF84


// serial
#bit serial_rx_hw = PORT_C.7
#bit serial_tx_hw = PORT_C.6
#BYTE	SPBRG	= 0xFAF
#BYTE	TXSTA	= 0xFAC
#BYTE RCSTA = 0xFAB
#bit serial_tx_bit9 = TXSTA.0
#bit serial_usart_enable = RCSTA.7

#bit serial_485_tx_enable = PORT_C.5

// knobs n buttons n switches
#bit pot_1 = PORT_A.0	// Analog 0
#bit pot_2 = PORT_A.1	// Analog 1
#bit ext_sw_1_usb_serin_to_pic = PORT_B.0
#bit ext_sw_2_usb_serout_to_pc = PORT_B.1
#bit dipsw_2 = PORT_B.5
#bit dipsw_3 = PORT_B.4
#bit dipsw_4 = PORT_B.2
#bit pgd_pb_1 = PORT_B.7
#bit pgc_pb_2 = PORT_B.6
#bit bcd_a = PORT_A.3
#bit bcd_b = PORT_A.2	// fix here, easier than patch board.  Fix schematic and
						// part model for V1b.
#bit bcd_c = PORT_A.4

// transistors
#bit t16 = PORT_B.3
#bit t15 = PORT_C.2
#bit t14 = PORT_C.1
#bit t13 = PORT_C.0
#bit t12 = PORT_E.2
#bit t11 = PORT_E.1
#bit t10 = PORT_E.0
#bit t9 = PORT_A.5
#bit t8 = PORT_D.7
#bit t7 = PORT_D.6
#bit t6 = PORT_D.5
#bit t5 = PORT_D.4
#bit t4 = PORT_D.3
#bit t3 = PORT_D.2
#bit t2 = PORT_D.1
#bit t1 = PORT_D.0


// misc
#bit misc_LED_anode = PORT_C.4
#bit misc_LED_cathode = PORT_C.3
#bit osc2 = PORT_A.6	// xtal on this pin


#define LED_OFF 0
#define LED_RED	1
#define LED_GREEN	2

uInt8 g_LEDstate;


const char Build_Date[] = __DATE__;
const char Build_Time[] = __TIME__;
const char Build_Version[] = "leoprogrammable testcode\n\r";

void output_dmx_frame_start();
void do_dmx_chase(uInt16 dmx_end, uInt8 stepBy);


// -----------------------------------------------------------------------
void set_led_state(uInt8 state)
{
	if (state == LED_OFF)
	{
		misc_LED_cathode= 0;
		misc_LED_anode= 0;
	}
	else if (state == LED_RED)
	{
		misc_LED_cathode= 1;
		misc_LED_anode= 0;
	}
	else	// green
	{
		misc_LED_cathode= 0;
		misc_LED_anode= 1;
	}

	g_LEDstate= state;
}



// -----------------------------------------------------------------------
uInt8 get_led_state()
{
	return g_LEDstate;
}



// -----------------------------------------------------------------------
// do dmx frame start stuff
void output_dmx_frame_start()
{
	// start of frame sync stuff
	serial_usart_enable= 0; // turn off usart hardware momentarily, so
													// we can set the output pin the way we want
	serial_tx_hw= 0;	// send a low - frame start sync
	delay_us(100);	// frame start sync: 88us minimum required
	serial_tx_hw= 1;
	delay_us(10);	// mark-after-break ... 8us minimum
	serial_usart_enable= 1; // turn back on usart hardware

	// output start code: 0= dimmer data
	fputc(0, DMX);
}



// -----------------------------------------------------------------------
main()
{
	uInt8 temp8;
	uInt8 seq;
	
#ifdef DO_ICD
	setup_wdt(WDT_OFF);
#else
	setup_wdt(WDT_ON);
#endif

	PORT_A= 0;
	PORT_B= 0;
	PORT_C= 0;
	PORT_D= 0;
	PORT_E= 0;

/*
#bit pot_1 = PORT_A.0	// Analog 0
#bit pot_2 = PORT_A.1	// Analog 1
#bit bcd_a = PORT_A.2
#bit bcd_b = PORT_A.3
#bit bcd_c = PORT_A.4
#bit t9 = PORT_A.5
#bit osc2 = PORT_A.6	// xtal on this pin

#bit ext_sw_1_usb_serin_to_pic = PORT_B.0
#bit ext_sw_2_usb_serout_to_pc = PORT_B.1
#bit dipsw_4 = PORT_B.2
#bit t16 = PORT_B.3
#bit dipsw_3 = PORT_B.4
#bit dipsw_2 = PORT_B.5
#bit pgc_pb_2 = PORT_B.6
#bit pgd_pb_1 = PORT_B.7

#bit t13 = PORT_C.0
#bit t14 = PORT_C.1
#bit t15 = PORT_C.2
#bit misc_LED_cathode = PORT_C.3
#bit misc_LED_anode = PORT_C.4
#bit serial_485_tx_enable = PORT_C.5
#bit serial_tx = PORT_C.6
#bit serial_rx = PORT_C.7

#bit t10 = PORT_E.0
#bit t11 = PORT_E.1
#bit t12 = PORT_E.2

#bit t8 = PORT_D.7
#bit t7 = PORT_D.6
#bit t6 = PORT_D.5
#bit t5 = PORT_D.4
#bit t4 = PORT_D.3
#bit t3 = PORT_D.2
#bit t2 = PORT_D.1
#bit t1 = PORT_D.0
*/
	// set direction.  1= input, 0= output.
	//
	set_tris_a(0b00011111);	// A0 & A1 analog ins, bcd digital in
	// for enternal switch input:
//	set_tris_b(0b11110111);
	// for usb serial i/o:
	set_tris_b(0b11110101);
	set_tris_c(0b10000000);
	set_tris_d(0);
	set_tris_e(0);

	// portB pullups.  1= on, 0= off.
	port_b_pullups(0b11110111);	// all but T16

	// adc.  make AN0 and AN1 inputs, 10bit.  (set with #device ADC=10 at top)
	setup_adc(ADC_CLOCK_INTERNAL);
	setup_adc_ports(AN0_TO_AN1);
	
	setup_psp(PSP_DISABLED);
	
	// ---------------
	// tell 'em we are booting
	set_led_state(LED_OFF);
	fprintf(DEBUG_SERIAL,"\n\r*********************************\n\r");
	fprintf(DEBUG_SERIAL,"Build date: %s, Time: %s\n\r", Build_Date,Build_Time);
	fprintf(DEBUG_SERIAL,"Version: %s\n\r", Build_Version);
	fprintf(DEBUG_SERIAL,"CCS PCH compiler version: %s\n",
			getenv("VERSION_STRING"));

	// ---------------
	// blink the heartbeat LED to show "boot"
	for (temp8=0; temp8<5; temp8++)
	{
		restart_wdt();
		set_led_state(LED_GREEN);
		delay_ms(100);
		set_led_state(LED_RED);
		delay_ms(100);
	}
	set_led_state(LED_OFF);
	restart_wdt();

	serial_485_tx_enable= 1;	// turn on 485 transmitter chip
//	serial_485_tx_enable= 0;	// turn off
	serial_tx_bit9= 1;	// we want 2 stop bits.  Do this by having 9th
						// bit transmit enabled and always have it high.

	seq= 0;
	
	while (1)
	{
		uInt16 pot1, pot2;
		uInt8 bcd;
		uInt8 pb1, pb2, sw1, sw2;
		uInt8 dipsw;
		
		// pots
		set_adc_channel(0);
		delay_ms(5);
		pot1= read_adc();
		pot1= 1024 - pot1;	// pot1 decreases as you turn it clockwise, opposite
			// of pot2, fix it to be more logical
		set_adc_channel(1);
		delay_ms(5);
		pot2= read_adc();

		// bcd
		bcd= 0;
		if (bcd_a == 0)
			bit_set(bcd,0);
		if (bcd_b == 0)
			bit_set(bcd,1);
		if (bcd_c == 0)
			bit_set(bcd,2);
		
		// buttons & switches
		pb1= !pgd_pb_1;
		pb2= !pgc_pb_2;
		sw1= !ext_sw_1_usb_serin_to_pic;
		sw2= !ext_sw_2_usb_serout_to_pc;
		dipsw= 0;
		if (dipsw_4 == 0)
			bit_set(dipsw,0);
		if (dipsw_3 == 0)
			bit_set(dipsw,1);
		if (dipsw_2 == 0)
			bit_set(dipsw,2);

		t1= 0;
		delay_cycles(1);
		t2= 0;
		delay_cycles(1);
		t3= 0;
		delay_cycles(1);
		t4= 0;
		delay_cycles(1);
		t5= 0;
		delay_cycles(1);
		t6= 0;
		delay_cycles(1);
		t7= 0;
		delay_cycles(1);
		t8= 0;
		delay_cycles(1);
		t9= 0;
		delay_cycles(1);
		t10= 0;
		delay_cycles(1);
		t11= 0;
		delay_cycles(1);
		t12= 0;
		delay_cycles(1);
		t13= 0;
		delay_cycles(1);
		t14= 0;
		delay_cycles(1);
		t15= 0;
		delay_cycles(1);
		t16= 0;
		delay_cycles(1);
		
		switch (seq) {
			case 0:	t1= 1;	break;
			case 1:	t2= 1;	break;
			case 2:	t3= 1;	break;
			case 3:	t4= 1; break;
			case 4: t5= 1; break;
			case 5:	t6= 1; break;
			case 6: t7= 1; break;
			case 7:	t8= 1; break;
			case 8: t9= 1; break;
			case 9:	t10= 1; break;
			case 10:t11= 1; break;
			case 11:t12= 1; break;
			case 12:t13= 1; break;
			case 13:t14= 1; break;
			case 14:t15= 1; break;
			case 15:t16= 1; break;
			default:
				break;
		}
		
		/*
		if (seq == 0)
		{
			t3= 0;
			delay_cycles(1);	// PIC bug, basically, this is required
			t1= 1;
		}
		else if (seq == 1)
		{
			t1= 0;
			delay_cycles(1);	// PIC bug, basically, this is required
			t2= 1;
		}
		else if (seq == 2)
		{
			t2= 0;
			delay_cycles(1);	// PIC bug, basically, this is required
			t3= 1;
		}
		*/

		/*
		restart_wdt();		
		t1= 1;
		delay_ms(20);
		t1= 0;
//		delay_cycles(1);
		
		t2= 1;
		delay_ms(20);
		t2= 0;
		delay_ms(20);
		*/
		
		output_dmx_frame_start();
		for (temp8= 0; temp8 < 16; temp8++)
		{
			if (temp8 == seq)
				fputc(255,DMX);
			else
				fputc(0,DMX);
		}
				
		fprintf(DEBUG_SERIAL,"seq# %02u: bcd= %u, pb1= %u, pb2= %u, sw1= %u, sw2= %u, dipsw= %u, pot1= %lu, pot2= %lu\n\r",
			seq,bcd, pb1,pb2, sw1,sw2, dipsw, pot1,pot2);
		restart_wdt();
		delay_ms(100);
		set_led_state(LED_GREEN);
		delay_ms(100);
		set_led_state(LED_OFF);
		seq++;
		if (seq == 16)
			seq= 0;
	}
	
	return 0;
}

