📄 mc1319x.c
字号:
/* 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 + -