#define F_CPU 8000000UL

#include <stdio.h>
#include <stdint.h>
#include <avr/io.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include "CYWUSB693x.h"




#define BV(bit) (1<<(bit)) // Byte Value => converts bit into a byte value. One at bit location.
#define cbi(reg, bit) reg &= ~(BV(bit)) // Clears the corresponding bit in register reg
#define sbi(reg, bit) reg |= (BV(bit))              // Sets the corresponding bit in register reg

#define HEX__(n) 0x##n##UL

#define B8__(x) ((x&0x0000000FLU)?1:0)  \
  +((x&0x000000F0LU)?2:0)  \
  +((x&0x00000F00LU)?4:0)  \
  +((x&0x0000F000LU)?8:0)  \
  +((x&0x000F0000LU)?16:0) \
  +((x&0x00F00000LU)?32:0) \
  +((x&0x0F000000LU)?64:0) \
  +((x&0xF0000000LU)?128:0)

#define B8(d) ((unsigned char)B8__(HEX__(d)))

#define CYWM_SCK		PB1 // Output
#define CYWM_MISO		PB3	// Input
#define CYWM_MOSI		PB2	// Output
#define CYWM_nSS		PB0	// Output	

#define CYWM_nRESET		PD0	// Output
#define CYWM_IRQ		PD1 // Input

#define low(port, pin) (port &= ~_BV(pin))
#define high(port, pin) (port |= _BV(pin))



#ifndef F_CPU
#define F_CPU 			8000000       	// Mhz 
#endif
#define UART_BAUD_RATE		9600      	// 9600 baud

void uart0_init(void);

int uart_putchar(char c, FILE *stream);

int uart_putchar(char c, FILE *stream) {

  //  if (c == '\n') uart_putchar('\r', stream);
  loop_until_bit_is_set(UCSR0A, UDRE);
  UDR0 = c;

  return 0;
}


void SPI_Write(uint8_t byte)
{
	SPDR = byte;				// Send SPI byte
	while(!(SPSR & (1<<SPIF)));	// Wait for SPI transmission complete
}

void CYWM_WriteReg(uint8_t which, uint8_t data)
{
	low(PORTB, CYWM_nSS);
	SPI_Write(REG_WRITE | which);
	SPI_Write(data);
	high(PORTB, CYWM_nSS);
}

uint8_t CYWM_ReadReg(uint8_t which) 
{
	low(PORTB, CYWM_nSS);
	SPI_Write(which);
	SPI_Write(which);
	high(PORTB, CYWM_nSS);
	return SPDR;
}


// Delay hekto-seconds :P
void delay_hs(uint16_t hs) 
{
	uint16_t n;
	for (n=0; n<hs; n++) {
		_delay_ms(10);
	}
}



void uart0_init(void) {
  unsigned char baudrateDiv;

  baudrateDiv = (unsigned char)((F_CPU+(UART_BAUD_RATE*8L))/(UART_BAUD_RATE*16L)-1);
  	
  UBRR0H = baudrateDiv >> 8;	
  UBRR0L = baudrateDiv;
	
  UCSR0B = (1 << RXEN0) | (1 << TXEN0);
  UCSR0C = (1 << USBS0) | (3 << UCSZ0);

  fdevopen(uart_putchar, NULL);
  printf("\n\nuart0_init();\n");
}

int main(void)
{
  unsigned char data, n, i;

  uart0_init();

  // init radio

	cli();	// Disable interrupts

	// Set port I/O directions
	DDRB = _BV(CYWM_SCK) | _BV(CYWM_MOSI) | _BV(CYWM_nSS);
	DDRD = _BV(CYWM_nRESET);
	//	DDRD = 0;
	
	// Setup SPI
	SPCR = _BV(SPE) | _BV(MSTR) | _BV(SPR0); // _BV(SPIE)
	//SPSR = _BV(SPI2X);	// Fast SPI

	// Setup interrupts
	MCUCR = _BV(ISC01) | _BV(ISC00); // Trigger INT0 on rising edge
	//GICR = _BV(INT0); // Enable INT0

	// Set initial pin states
	high(PORTB, CYWM_nSS);

	// Enable radio
	//	high(PORTC, CYWM_nPD);
	high(PORTD, CYWM_nRESET);


	// Setup radio
	// Test
	data = CYWM_ReadReg( REG_ID );
	if (data == 0x07) {
		printf("REG_ID == 0x07: OK!\n\r");
	}
	else {
		printf("REG_ID == 0x07: Failed!\n\r");
	}


	CYWM_WriteReg( REG_CLOCK_MANUAL, 0x41 );
	CYWM_WriteReg( REG_CLOCK_ENABLE, 0x41 );	
	CYWM_WriteReg( REG_CONTROL, 0x10 );	      
	CYWM_WriteReg( REG_ANALOG_CTL, 0x44 );			
	CYWM_WriteReg( REG_CRYSTAL_ADJ, 0x40 );			
	CYWM_WriteReg( REG_VCO_CAL, 0xC0 );	    


  while (1) {

    for (i=0;i<82;i++){
    //cycle through channels. get RSSI and print value

      CYWM_WriteReg( REG_CONTROL, 0x80 + 0x10);		   

      CYWM_WriteReg( REG_CHANNEL, i);

      data = CYWM_ReadReg( REG_CHANNEL );
      data = CYWM_ReadReg( REG_CHANNEL );
      data = CYWM_ReadReg( REG_CHANNEL );

      CYWM_WriteReg( REG_CARRIER_DETECT, 0x00 );	    
      CYWM_WriteReg( REG_CARRIER_DETECT, 0x80 );	    
      
      data = CYWM_ReadReg( REG_RSSI );

      printf("%c]%c", i, data);

      //        spi_write_addr(p, 0x00 + 0x10, REG_CONTROL);

      CYWM_WriteReg( REG_CONTROL, 0x00 + 0x10 );	    

    }
  }  
}



