⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mc1319x.c

📁 zigbee Interface an Atmel AVR MCU with Freescales MC1319x ZigBee chip
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Interface an Atmel AVR MCU with Freescales MC1319x ZigBee chip */

/*
 * Author: johan@anteeo.se
 *
 * Copyright (C) 2005 by Anteeo Systems HB, Sweden
 *
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * 
 * Created:     Fri May 13 22:46:58 2005, johan@anteeo.se
 *
 */


#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdio.h>

#include <mc1319x.h>
#include <ledfeedback.h>
#ifdef USE_USART
#include <usart.h>
#else
#define USART_TransmitStr(x)
#define USART_Transmit(x,y)
#endif

// Status and mode
char DSRC_Status;

void SPI_MasterInit(void)
{
	// Set MOSI and SCK to output
	// IMPORTANT to set DD_SS to output, otherwise SPI will not work reliably!
	DDR_SPI|=(1<<DD_MOSI)|(1<<DD_SCK)|(1<<DD_SS);
	// Enable SPI, Master, clock rate fck/2
	SPCR=(1<<SPE)|(1<<MSTR);
	SPSR|=_BV(SPI2X);
}

void MC1319x_MCU_Init(void)
{
	DSRC_Status=0;

	// Set RST high, the rest low
	// Important to do this BEFORE we set RST pin to output,
	// otherwise we will reset the MC1319x and the clock will die!
	DR_13192CTRL= _BV(DD_RST)|_BV(DD_ATTN)|_BV(DD_CE);
	// Set RST to output
	DDR_13192CTRL=_BV(DD_RST)|_BV(DD_RXTXEN)|_BV(DD_ATTN)|_BV(DD_CE);

	SPI_MasterInit();
}

void SPI_Read13192Register(unsigned char reg, unsigned short *word)
{
	// Set CE to low, indicate start of transaction
	DR_13192CTRL&= ~_BV(DD_CE);
	
	SPDR=MC13192_HEADER_RW|reg;
	// Wait for header byte write to finish
	while(!(SPSR&(1<<SPIF)));
	*word=SPDR;

	// Start SPI clock by sending a byte
	SPDR=0;
	// Wait for first read byte to finish
	while(!(SPSR&(1<<SPIF)));
	*word=(SPDR<<8);

	// Start SPI clock by sending a byte
	SPDR=0;
	// Wait for second read byte to finish
	while(!(SPSR&(1<<SPIF)));
	*word|=(SPDR);
	
	// Set CE to high, indicate end of transaction
	DR_13192CTRL|= _BV(DD_CE);
}

void SPI_Write13192Register(unsigned char reg, unsigned short word)
{
	// Set CE to low, indicate start of transaction
	DR_13192CTRL&= ~_BV(DD_CE);
	
	SPDR=reg&~MC13192_HEADER_RW;
		// Wait for write to finish
	while(!(SPSR&(1<<SPIF)));
	SPDR=(word>>8);
	// Wait for write to finish
	while(!(SPSR&(1<<SPIF)));
	SPDR=word&0xFF;
	// Wait for write to finish
	while(!(SPSR&(1<<SPIF)));
	
	// Set CE to high, indicate end of transaction
	DR_13192CTRL|= _BV(DD_CE);
}


void SPI_Modify13192Register(unsigned char reg, unsigned short mask, unsigned short word)
{
	unsigned short word_tmp;
	SPI_Read13192Register(reg, &word_tmp);
	SPI_Write13192Register(reg, (word_tmp& ~mask)|(word & mask) );
}

// Packet buffer
unsigned char packetBuf[128];
// Position in the buffer
unsigned char packetPos;
// Size of the packet
unsigned char packetSize;

void MC13192Init(void)
{
	cli();
	packetSize=0;
	packetPos=0;
	unsigned short tmp;

	// Disable timers
	SPI_Write13192Register(0x1b, 0x8000);
	SPI_Write13192Register(0x1d, 0x8000);
	SPI_Write13192Register(0x1f, 0x8000);
	SPI_Write13192Register(0x21, 0x8000);
	
	// Set MISO signal strength to max and IRQ pullup enable
	SPI_Modify13192Register(0x0c, 0x0380,0x0380);
	// Set clock to 8MHz
	SPI_Modify13192Register(0x0a, 0x0007, 0x0001);

	// Set reset-bit
	SPI_Read13192Register(0x25, &tmp);

	// Mandatory hidden register settings
	SPI_Modify13192Register(0x08,0x012,0x0012);
	SPI_Write13192Register(0x08,0xFFF7); // Voodoo
	SPI_Modify13192Register(0x11,0x0300,0x0000);
	SPI_Modify13192Register(0x06,0x4000,0x4000);
	
	// Disabe ATTN, enable timer1 IRQ
	//SPI_Modify13192Register(0x04,0x820F,0x0201);
	// Set transmit power to max
	//SPI_Modify13192Register(0x12, 0x00F0, 0x00F0);
	// Set transmit power to min
	SPI_Modify13192Register(0x12, 0x00F0, 0x0000);

	// Enable pll_lock and timer1 irq
	SPI_Modify13192Register(MC13192_IRQ_MASK,cDOZE_MASK|cPPL_LOCK_MASK|cTMR1_MASK|cSTRM_DATA_MASK,cPPL_LOCK_MASK|cTMR1_MASK|cSTRM_DATA_MASK);
	// Enable irq CCA, TX_SENT, RX_RCVD
	SPI_Modify13192Register(0x06,0x0720,0x0720);

	// Clear pending IRQs
	SPI_Read13192Register(MC13192_IRQ_STATUS, &tmp);

	// Check a know reg to see if the SPI-link is working
	SPI_Read13192Register(0x0a, &tmp);
	if( (tmp&0x7)==1)
	{
		// Set clock to 16MHz
		SPI_Modify13192Register(0x0a, 0x0007, 0x0000);
		DSRC_Status=DSRC_INIT_OK;
	}
/*	SPI_Read13192Register(0x1b, &tmp);
	if(tmp!=0x8000)
	{
		DSRC_Status=0;
	}*/
	sei();
}

void MC13192_SendNextPacketWord(void)
{
	unsigned short data;
	if(packetPos < packetSize)
	{
		data=(((unsigned short)packetBuf[packetPos++])<<8);
		data|=packetBuf[packetPos++]&0xFF;
		SPI_Write13192Register(MC13192_TX_PKT_RAM, data);
	}
}

void MC13192_ReceiveNextPacketWord(void)
{
	unsigned short data;
	if(packetPos < packetSize)
	{
		SPI_Read13192Register(MC13192_RX_PKT_RAM, &data);
		packetBuf[packetPos++]=(data>>8);
		packetBuf[packetPos++]=data&0xFF;
	}
}

void MC13192_sendPacket(char size)
{
	cli();
	// Check if init ok and no active transfers
	if( DSRC_Status==(DSRC_INIT_OK|DSRC_RCVTMR) )
	{
		DSRC_Status=DSRC_ABORTRCV;
		// Disable TC1 and clear IRQ
		SPI_Write13192Register(MC13192_TMR_CMP1_A, 0x8000);
		// Set RXTXEN low to abord stream receive mode
		DR_13192CTRL &= ~_BV(DD_RXTXEN);
		sei();
		return;
	}
	if( DSRC_Status!=DSRC_INIT_OK )
	{
#ifdef USE_USART
		char szBuf[32];
		sprintf(szBuf, "Cant send; Status 0x%x\r\n",DSRC_Status);
		USART_TransmitStr( szBuf);
#endif
		sei();
		return;
	}
		
	DSRC_Status|=DSRC_SND;
	packetSize=size;
	packetPos=0;
	
	// Set TX frequency
	
	// Set RXTXEN low
	DR_13192CTRL &= ~_BV(DD_RXTXEN);

	// Set TX control bits
	SPI_Modify13192Register(MC13192_CONTROL_A,cRX_STRM|cTX_STRM|cTMR_TRIG_EN,0x0000);
	SPI_Modify13192Register(MC13192_CONTROL_B,cUSE_STRM_MODE,cUSE_STRM_MODE);

	// Enable GPIO1 and GPIO2 status interface to MCU
	// GPIO1 indicates when the MC13192 is out of idle. 
	// GPIO2 indicates a valid CRC or CCA result.
	SPI_Modify13192Register(MC13192_CONTROL_C,cGPIO_ALT_EN,cGPIO_ALT_EN);

	// Enable irq when a word of TX payload data needs to be written
	SPI_Modify13192Register(MC13192_CONTROL_A,cTX_SENT_MASK,cTX_SENT_MASK);
	// Enable irq when the TX packet has been fully sent
	SPI_Modify13192Register(MC13192_CONTROL_B,cTX_DONE_MASK,cTX_DONE_MASK);

	// Set packet size (+2 for FCS data, which is generated by MC13192, dont send it!)
	SPI_Modify13192Register(MC13192_TX_PKT_CTL,cTX_PKT_LENGTH,size+2);

	// Load MC13192 with the first word of the packet data
	MC13192_SendNextPacketWord();

	// Enable stream TX sequence
	SPI_Modify13192Register(MC13192_CONTROL_A,cTX_STRM,cTX_STRM);

	// Set RXTXEN high
	DR_13192CTRL |= _BV(DD_RXTXEN);
	sei();
}

unsigned long MC13192_getCurrentTime(void)
{
	unsigned short tmp;
	unsigned long timeHigh, timeLow, time;
	SPI_Read13192Register(MC13192_CURRENT_TIME_A, &tmp);
	timeHigh=tmp;
	SPI_Read13192Register(MC13192_CURRENT_TIME_B, &tmp);
	timeLow=tmp;
	time=(unsigned long) ((timeHigh&0x0000FFFF)<<16)|timeLow;
	return time;
}

unsigned short MC13192_timeToMs(unsigned long time)
{
	// Event timer is running on 250000Hz at default
	return time*1000/250000;
}

void MC13192_setTimeout(unsigned long timeout)
{
	timeout+=MC13192_getCurrentTime();

	// Disable TC1 and clear IRQ
	SPI_Write13192Register(MC13192_TMR_CMP1_A, 0x8000);
	// Load timeout value and start timer
	SPI_Write13192Register(MC13192_TMR_CMP1_B, timeout&0x0000FFFF);
	SPI_Write13192Register(MC13192_TMR_CMP1_A, (timeout>>16)&0x000000FF);
	SPI_Write13192Register(MC13192_TMR_CMP1_B, (unsigned short) (timeout&0x0000FFFF) );
}

unsigned char MC13192_receivePacket(unsigned long timeout)
{
	cli();
	// Check if init ok and no active transfers
	if(DSRC_Status!=DSRC_INIT_OK)
	{
#ifdef USE_USART
		char szBuf[32];
		sprintf(szBuf, "Cant receive; Status 0x%x\r\n",DSRC_Status);
		USART_TransmitStr( szBuf);
#endif
		sei();
		return 0;
	}

	if(timeout!=0)
	{
		DSRC_Status|=DSRC_RCVTMR;
		MC13192_setTimeout(timeout);
	}
	else
		DSRC_Status|=DSRC_RCV;
	
	packetPos=0;
	packetSize=0;
	
	// Set TX frequency
	
	// Set RXTXEN low
	DR_13192CTRL &= ~_BV(DD_RXTXEN);

	// Set RX control bits
	SPI_Modify13192Register(MC13192_CONTROL_A,cRX_STRM|cTX_STRM|cTMR_TRIG_EN,0x0000);
	SPI_Modify13192Register(MC13192_CONTROL_B,cUSE_STRM_MODE,cUSE_STRM_MODE);

	// Enable GPIO1 and GPIO2 status interface to MCU
	// GPIO1 indicates when the MC13192 is out of idle. 
	// GPIO2 indicates a valid CRC or CCA result.
	SPI_Modify13192Register(MC13192_CONTROL_C,cGPIO_ALT_EN,cGPIO_ALT_EN);

	// Enable irq when a word of RX payload data needs to be read
	SPI_Modify13192Register(MC13192_CONTROL_A,cRX_RCVD_MASK,cRX_RCVD_MASK);
	// Enable irq when the RX packet has been fully recived
	SPI_Modify13192Register(MC13192_CONTROL_B,cRX_DONE_MASK,cRX_DONE_MASK);

	// Enable stream RX sequence
	SPI_Modify13192Register(MC13192_CONTROL_A,cRX_STRM,cRX_STRM);

	// Set RXTXEN high

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -