/**********************************************/
/* Example Program For ET-BASE Z51F6412 V1.0  */
/* MCU      : Zilog MCS51 / Z51F6412          */
/*          : Run Internal RC (8.00 MHz)      */
/* Compiler : Keil C51 (V9.50a)               */
/* Editor   : uVision V4.53.0.6               */
/* Write By : Eakachai Makarn(ETT CO.,LTD.)   */
/* Function : Demo SPI0,SPI1                  */
/* Update   : 18 August 2012                  */
/**********************************************/
//
// Test Demo SPI with "ET-MINI 74HC595" Board
//
// SPI0 Interface
// ET-BASE Z51F66412 <-----> ET-MINI 74HC595
// P3.4(SS0#)        ------> LATCH
// P3.5(SCK0)        ------> CLOCK
// P3.6(MOSI0)       ------> DIN
// P3.7(MISO0)       <------ NC
//
// SPI1 Interface
// ET-BASE Z51F66412 <-----> ET-MINI 74HC595
// P4.4(SS1#)        ------> LATCH
// P4.5(SCK1)        ------> CLOCK
// P4.6(MOSI1)       ------> DIN
// P4.7(MISO1)       <------ NC

// ET-BASE Z51F6412 Hardware Statdard I/O
// SW1    = P8[0] GPIO Input
// LED    = P8[1] GPIO Output
// BUZZER = P5[0] Buzzer Drive
// UART0  = P0[2]:TX0,P0[3]:RX0
// UART1  = P3[2]:TX1,P3[3]:RX1
//
#include <z51f6412.h>																							// Z8051 : Z51F6412

/******************************************/
/* ET-BASE Z51F6412 Hardware System Clock */
/******************************************/
#define FREQ_32KHZ    			(32768ul)															// 32.768 KHz
#define FREQ_125KHZ					(125000ul)														// 125 KHz
#define FREQ_1MHZ						(1000000ul)														// 1.00 MHZ
#define FREQ_2MHZ						(2000000ul)														// 2.00 MHz
#define FREQ_4MHZ						(4000000ul)   												// 4.00 MHz
#define FREQ_8MHZ						(8000000ul)   												// 8.00 MHz
#define FREQ_10MHZ					(10000000ul)   												// 10.00 MHz
#define FREQ_12MHZ					(12000000ul)  												// 12.00 MHz
#define FREQ_16MHZ					(16000000ul)  												// 16.00 MHz
#define FREQ_PLL	    			(14745600ul)  												// 14.7456MHz
#define MY_FREQ							FREQ_8MHZ

/*******************************************/
/* ET-BASE Z51F6412 Hardware UART Baudrate */
/*******************************************/
#define BAUD_1200     			(1200ul)															// 1200
#define BAUD_2400     			(2400ul)															// 2400
#define BAUD_4800     			(4800ul)															// 4800
#define BAUD_9600     			(9600ul)															// 9600
#define BAUD_19200    			(19200ul)															// 19200
#define BAUD_38400    			(38400ul)															// 38400
#define BAUD_57600    			(57600ul)															// 57600
#define BAUD_115200   			(115200ul)														// 115200
#define MY_BAUD							BAUD_9600					
	
/************************************/
/* ET-BASE Z51F6412 Hardware SW Pin */
/************************************/
#define SW_PIN							(1 << 0)															// P8[0] = SW
#define SW_PORT_DIR					P8IO																	// Port Direction
#define SW_PORT_DATA				P8																		// Port Data
#define SW_PORT_PULLUP			P8PU																	// Port Pull-Up
#define SW_PORT_DEBOUNCE		P8DB																	// Port Debounce
#define SW_PORT_INIT() 			SW_PORT_DIR      	&= ~(SW_PIN)				// SW = Input 
#define SW_LOGIC_INIT()     SW_PORT_DATA     	|=  (SW_PIN)				// SW Defualt Logic = "1"
#define SW_PULLUP_INIT()		SW_PORT_PULLUP   	|=  (SW_PIN)				// Enable Pull-Up SW Pin
#define SW_DEBOUNCE_INIT()  SW_PORT_DEBOUNCE 	|=  (SW_PIN)				// Enable Debounce SW Pin

/*************************************/
/* ET-BASE Z51F6412 Hardware LED Pin */
/*************************************/
#define LED_PIN							(1 << 1)															// P8[1] = LED
#define LED_PORT_DIR				P8IO
#define LED_PORT_DATA 			P8
#define LED_PORT_INIT()    	LED_PORT_DIR 			|=  (LED_PIN)				// LED = Output
#define LED_OFF()						LED_PORT_DATA			&= ~(LED_PIN) 			// LED Pin = 0
#define LED_ON()  					LED_PORT_DATA			|=  (LED_PIN) 			// LED Pin = 1
#define LED_TOGGLE()  			LED_PORT_DATA			^=  (LED_PIN) 			// LED Pin = Toggle

/*************************************/
/* ET-BASE Z51F6412 Hardware SPI Pin */
/*************************************/
#define SPI0_CS_PIN	  			(1 << 4)															// P3[4] = CS0#
#define SPI0_PORT_DIR				P3IO
#define SPI0_PORT_DATA			P3
#define SPI0_CS_INIT()  		SPI0_PORT_DIR 		|=  (SPI0_CS_PIN)
#define SPI0_CS_LOW()				SPI0_PORT_DATA  	&= ~(SPI0_CS_PIN)
#define SPI0_CS_HIGH()  		SPI0_PORT_DATA  	|=  (SPI0_CS_PIN)

#define SPI1_CS_PIN	  			(1 << 4)															// P4[4] = CS1#
#define SPI1_PORT_DIR				P4IO
#define SPI1_PORT_DATA			P4
#define SPI1_CS_INIT()  		SPI1_PORT_DIR 		|=  (SPI1_CS_PIN)
#define SPI1_CS_LOW()				SPI1_PORT_DATA  	&= ~(SPI1_CS_PIN)
#define SPI1_CS_HIGH()  		SPI1_PORT_DATA  	|=  (SPI1_CS_PIN)
 
/***********************
 * Function Prototypes *
 ***********************/
void init_spi0(void);
void init_spi1(void);
unsigned char spi0_read_write(unsigned char ch);
unsigned char spi1_read_write(unsigned char ch);
void delay(unsigned long);																				// Delay Time Function(1..4294967295)


/********************
 * Function: main() *
 ********************/
void main(void)
{	  
	unsigned char data_out;
	
	/* Config System Clock = Internal RC 8.00 MHz */
	//PLLCR = 0,0,0,00,00,0
	// 0xxxxxxx : PLL Output Status
	// x0xxxxxx : PLL Output Bypass
	// xx0xxxxx : Power PLL = Default
	// xxx00xxx : FBDiv = Default
	// xxxxx00x : PLL M = Default
	// xxxxxxx0 : PLL Disable
	PLLCR = 0x00;																										// Disable PLL
	
	// SCCR = 0,01,0,0,1,00
	// 0xxxxxxx : Stop Mode = Mode 2
	// x01xxxxx : INTRC Clock Divide = INTRC(16MHz)/2 = 8MHz
	// xxx0xxxx : Clock Change By Hardware
	// xxxx0xxx : RC Oscillator Enable
	// xxxxx1xx : XTAL Oscillator Disable
	// xxxxxx00 : System Clock Source = INTRC(16MHz)
	SCCR = 0x24;  																									// INT-RC 8MHz	
	/* Now System Clock = 8.00MHz */
  
	// Initial spi
	init_spi0();
  init_spi1();
  
	//Main Loop
	while(1)
	{
	  for (data_out = 0x01; data_out; data_out <<= 1)								// Shift Left (10000000 <- 00000001)
    { 
			spi0_read_write(~data_out);
			spi1_read_write(~data_out);
		  delay(25000);
		}
	} 
}

/*
 * Function    : init_spi0()
 * Description : initialize SPI resources
 *             : baudrates, parirty, stop bit
 */
void init_spi0(void)
{
	SPI0_CS_INIT();																									// CS0# = Output
	SPI0_CS_HIGH();																									// CS0# = High
	
	// SPICR0 = 1,0,1,00,101
  // 1xxxxxxx : SPI Enable
  // x0xxxxxx : MSB First
  // xx1xxxxx : SPI = Master
	// xxx00xxx : CPOL=0,CPHA=0
	// xxxxx101 : SPI Clock = Fx/8
	SPICR0 = 0xA5;

	// SPISR0 = 0,0,0,0,0,0,1,1
  // 0xxxxxxx : Default
  // x0xxxxxx : Default
	// xx0xxxxx : Default
	// xxx0xxxx : Reserve
	// xxxx0xxx : Reserve
	// xxxxx0xx : Disable SS Pin
	// xxxxxx1x : Enable TX
	// xxxxxxx1 : Enable RX
	SPISR0 = 0x03;
	
	// xxxxx0xx :	Disable SPI0 Interrupt									
	IE1 &= ~0x04;	
}

/*
 * Function    : init_uart1()
 * Description : initialize UART1 resources
 *             : baudrates, parirty, stop bit
 */
void init_spi1(void)
{
	SPI1_CS_INIT();																									// CS1# = Output
	SPI1_CS_HIGH();																									// CS1# = High
	
	// SPICR1 = 1,0,1,00,101
  // 1xxxxxxx : SPI Enable
  // x0xxxxxx : MSB First
  // xx1xxxxx : SPI = Master
	// xxx00xxx : CPOL=0,CPHA=0
	// xxxxx101 : SPI Clock = Fx/8
	SPICR1 = 0xA5;

	// SPISR1 = 0,0,0,0,0,0,1,1
  // 0xxxxxxx : Default
  // x0xxxxxx : Default
	// xx0xxxxx : Default
	// xxx0xxxx : Reserve
	// xxxx0xxx : Reserve
	// xxxxx0xx : Enable SS Pin
	// xxxxxx1x : Enable TX
	// xxxxxxx1 : Enable RX
	SPISR1 = 0x03;
	
	// xx0xxxxx :	Disable SPI1 Interrupt									
	IE3 &= ~0x20;
}

/*
 * Function    : spi0_read_write
 * Description : Output byte to spi0
 */
unsigned char spi0_read_write(unsigned char ch)
{
	unsigned char ch0;																							// Dummy Read
	
	SPI0_CS_LOW();																									// Enable CS0#
	SPIDR0 = ch;																										// Send Byte Data
  while(!(SPISR0 & 0x80));																				// Wait until Trammit Complete	
	ch0 = SPIDR0;																										// Read SPI1
	SPI0_CS_HIGH();																									// Disable CS0#
	
	return ch0;
}

/*
 * Function    : spi1_read_write
 * Description : Output byte to spi1
 */
unsigned char spi1_read_write(unsigned char ch)
{
	unsigned char ch1;																							// Dummy Read
	
	SPI1_CS_LOW();																									// Enable CS1#
	SPIDR1 = ch;																										// Send Byte Data
  while(!(SPISR1 & 0x80));																				// Wait until Trammit Complete	
	ch1 = SPIDR1;																										// Read SPI1
	SPI1_CS_HIGH();																									// Disable CS1#
	
	return ch1;
}

/*******************************************/
/* Long Delay Time Function(1..4294967295) */
/*******************************************/
void delay(unsigned long i)
{
  while(i > 0) {i--;}																							// Loop Decrease Counter	
  return;
}
