📄 rfdesign.c
字号:
//-----------------------------------------------------------------------------
// Initialization Functions
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
// SYSCLK_Init
//-----------------------------------------------------------------------------
//
// This routine initializes the system clock to use the internal 24.5MHz
// oscillator as its clock source. Also enables missing clock detector
// reset and enables the VDD monitor as a reset source.
//
void SYSCLK_Init (void)
{
OSCICN |= 0x03; // set clock to 24.5 MHz
RSTSRC = 0x06; // enable missing clock detector
}
//-----------------------------------------------------------------------------
// ADC0_Init
//-----------------------------------------------------------------------------
//
// Configure ADC0 to use Timer2 overflows as conversion source, and to
// generate an interrupt on conversion complete.
// Enables ADC end of conversion interrupt. Leaves ADC disabled.
//
void ADC0_Init(void)
{
REF0CN = 0x03; // set VREF pin as voltage reference,
// enable internal bias generator and
// internal reference buffer
ADC0CN = 0x02; // overflow on Timer 2 starts
// conversion
// ADC0 disabled and in normal
// tracking mode
AMX0P = 0x0B; // select P1.3 as positive conv. source
AMX0N = 0x11; // set ADC to single-ended mode
ADC0CF = (SYSCLK/3000000) << 3; // ADC Conversion clock = 3 MHz
ADC0CF&= ~0x04; // ADC readings are right-justified
EIE1 |= 0x08; // enable ADC0 EOC interrupt
}
//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// P0.0 - VREF
// P0.1 - IDAC0 Output
// P0.2 - SCLK
// P0.3 - PALE (Digital RF Control Signal)
// P0.4 - UART TX
// P0.5 - UART RX
// P0.6 - MISO
// P0.7 - MOSI
// P1.0 - CEX0
// P1.1 - RSSI Analog Input
// P1.2 - CHP_OUT (Open Drain)
// P1.3 - Analog Input (Incoming Signal)
// P1.4 -
void PORT_Init (void)
{
XBR0 = 0x03; // enable UART at P0.4 and P0.5
// and enable SPI
P0SKIP = 0x0B; // Skip VREF (P0.0), IDAC0(P0.1),
// and P0.3
P1SKIP = 0x5E; // Skip CEX0(P1.0), P1.1, P1.2,
// P1.3, P1.4, P1.6
XBR1 |= 0x41; // Enable crossbar, CEX0 at port pin
P0MDIN &= ~0x01; // set P0.0 to analog input
P0MDOUT |= 0x1C; // set P0.3 (PALE), UTX, SCLK to
// push-pull
P1MDIN &= ~0x0A; // Set P1.3, P1.1 as analog input
}
//-----------------------------------------------------------------------------
// SPI_Init
//-----------------------------------------------------------------------------
//
// Set SPI to master, CKPHA = 0, CKPOL = 1. Set SPI to 3 wire mode, and
// enable SPI. SPI0CKR = 11, SCLK = 24.5Mhz / 12 = 1.021 MHz.
//
void SPI_Init(void)
{
SPI0CFG = 0x50; // Master enable, CKPOL = 1
SPI0CKR = (SYSCLK / (2 * 1000000)) - 1;
// sets SPI clock to 1 MHz
SPI0CN = 0; // clear all flags
SPIEN = 1; // enable SPI
}
//-----------------------------------------------------------------------------
// IDAC0_Init
//-----------------------------------------------------------------------------
//
// Configure IDAC to update with every Timer 3 overflow, using 2.0 mA
// full-scale output current.
//
void IDAC0_Init(void)
{
IDA0CN &= ~0x70; // Clear Update Source Select Bits
IDA0CN |= 0x30; // Set DAC to update on Tmr 2 Overflows
IDA0CN |= 0x80; // Enable DAC
}
//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// Configure the UART0 using Timer1, for <BAUDRATE> and 8-N-1. UART interrupt
// is enabled.
//
void UART0_Init (void)
{
SCON0 = 0x00; // SCON0: 8-bit variable bit rate
// level of STOP bit is ignored
// RX disabled
// ninth bits are zeros
// clear RI0 and TI0 bits
if (SYSCLK/BAUDRATE/2/256 < 1) {
TH1 = -(SYSCLK/BAUDRATE/2);
CKCON &= ~0x0B; // T1M = 1; SCA1:0 = xx
CKCON |= 0x08;
} else if (SYSCLK/BAUDRATE/2/256 < 4) {
TH1 = -(SYSCLK/BAUDRATE/2/4);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 01
CKCON |= 0x01;
} else if (SYSCLK/BAUDRATE/2/256 < 12) {
TH1 = -(SYSCLK/BAUDRATE/2/12);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 00
} else {
TH1 = -(SYSCLK/BAUDRATE/2/48);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 10
CKCON |= 0x02;
}
TL1 = TH1; // init Timer1
TMOD &= ~0xf0; // TMOD: timer 1 in 8-bit autoreload
TMOD |= 0x20;
TR1 = 1; // START Timer1
IE |= 0x10; // Enable UART Interrupts
}
//
//-----------------------------------------------------------------------------
// PCA0_Init
//-----------------------------------------------------------------------------
//
// The PCA is used to check for valid data at the UART RX pin. Module 0
// is configured for edge-triggered captures, and count sysclocks.
// PCA interrupts are enabled. Leaves PCA disabled.
//
void PCA0_Init(void)
{
PCA0CPM0 |= 3<<4; // Set PCA to edge-capture on rising
// and falling edges
PCA0CPM0 |= 1; // enable CCF0 interrupts
PCA0MD |= 4<<1; // Set PCA0 to count sys clocks
EIE1 |= 0x10; // Enable PCA0 interrupts
}
//----------------------------------------------------------------------------
// Timer0_Init
//----------------------------------------------------------------------------
//
// Timer 0 is used by WaituS() to delay by a reliable amount of time.
// Timer 0 is set to overflow every 1us and is left disabled.
void Timer0_Init(void)
{
CKCON |= 0x04; // Timer 0 counts sysclocks
TMOD |= 0x02; // set Timer 0 to 8-bit counter with
// auto-reload
TL0 = -(SYSCLK/1000000); // to overflow at rate of 1us
TH0 = -(SYSCLK/1000000); // set reload value
}
//----------------------------------------------------------------------------
// Timer2_Init
//----------------------------------------------------------------------------
//
void Timer2_Init(unsigned int counts)
{
TMR2CN = 0x00; // resets Timer 2, sets to 16 bit mode
CKCON |= 0x10; // use system clock
TMR2RL = -counts; // Initial reload value
TMR2 = -counts; // init timer
ET2 = 0; // disable Timer 2 interrupts
TR2 = 1; // start Timer 2
}
//-----------------------------------------------------------------------------
// Timer3_Init
//-----------------------------------------------------------------------------
//
// Configure Timer3 to auto-reload at interval specified by <counts>
// using SYSCLK as its time base. Interrupts are enabled.
//
void Timer3_Init(unsigned int counts)
{
TMR3CN = 0x00; // resets Timer 3, sets to 16 bit mode
CKCON |= 0x40; // use system clock
TMR3RL = -counts; // Initial reload value
TMR3 = -counts; // init timer
EIE1 |= 0x80; // enable Timer 3 interrupts
TMR3CN = 0x04; // start Timer 3
}
//-----------------------------------------------------------------------------
// Interrupt Service Routines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// ADC0_ISR
//-----------------------------------------------------------------------------
// This routine captures and saves an audio input sample, and then
// compares it to past samples to find out whether or not the audio
// stream is quiet. The ISR also acts as a timer to measure the 250us
// delay when issuing an RX->TX or TX->RX command to the RF transceiver.
//
void ADC0_ISR(void) interrupt 10
{
unsigned short value;
AD0INT = 0;
value = ADC0;
// Checks for a quiet audio input. If signal falls within the
// CENTER_OF_WINDOW +/- CHANGEE_IN_VOLUME window, increment
// ADC_LOW up to SHUTDOWN_TOLERANCE. If it does not,
// reset ADC_LOW to 0.
if (((value > (CENTER_OF_WINDOW - CHANGE_IN_VOLUME)) &&
(value < (CENTER_OF_WINDOW + CHANGE_IN_VOLUME))) )
{
// ADC_LOW is used to determine whether LOCAL_SHUTDOWN_STATE
// should change from NO_ENDPOINTS_QUIET to ONE_ENDPOINT_QUIET
if (ADC_LOW != SHUTDOWN_TOLERANCE)
ADC_LOW++;
}
else
{
CENTER_OF_WINDOW = value; // current value outside of
// window should be set as the
// new center of the allowable
// values
ADC_LOW = 0; // reset counter because signal's
// amplitude has changed too much
// to be considered quiet
}
ADCRXFIFO_Push(ADC0); // save ADC value for compression
// TRANSITION_IN_PROGRESS is set at the end of an RX or TX session
// by C1000_RX_MODE or C1000_TX_MODE, after the CURRENT register is
// updated, because a 250 us delay is needed.
if(TRANSITION_IN_PROGRESS)
{
if(++TRANSITIONCOUNT == TRANSITION_COMPLETE)
{
// TO_TX_INDICATOR = 1 if RX->TX transition
if(TO_TX_INDICATOR)
{
UART_MODE = TX_MODE;
SETREG(PA_POW,0x80); // sets the RF TX output power
}
else // TX->RX transition
{
UART_MODE = RX_MODE;
}
TRANSITIONCOUNT = 0; // reset counter
TRANSITION_IN_PROGRESS = 0; // reset flag
}
}
}
//-----------------------------------------------------------------------------
// PCA0_ISR
//-----------------------------------------------------------------------------
// This ISR measures widths between level transitions on the UART RX pin
// and updates the RX_STATEMACHINE depending on these transition widths.
// In certain states, the ISR can lock the averaging filter or
// enable UART reception.
//
void PCA0_ISR(void) interrupt 11
{
static unsigned short newvalue = 0; // saves newest PCA0CP0 value
static unsigned short oldvalue = 0; // saves second most recent value
unsigned short width; // saves calculated bit width
// used to count the number of preamble bits found
static unsigned char preamble_count = 0;
CCF0 = 0; // Acknowledge interrupt
oldvalue = newvalue; // save value from last ISR
newvalue = PCA0CP0; // save newest value
width = newvalue - oldvalue; // calculate transition width
// This code looks for the sync byte in received data by
// watching for a 5-byte-wide transition width corresponding
// to the first (low logic level) nibble of 0x0F
// Remember that UART transmits bytes LSB first
if (RX_STATEMACHINE == RX_SEARCH_FOR_SYNCBYTE)
{
// Edges are counted at the beginning of the RX session
// to prevent the state machine from getting confused
// by noise output as data from the RF transceiver
if (++EDGES_THIS_SESSION > EDGES_TO_DISREGARD)
{
if( (width > 5 * (BAUDTOLERANCE * SYSCLK / BAUDRATE / 10))
&& (width < 5 * ( (20 - BAUDTOLERANCE) * SYSCLK / (BAUDRATE * 10) )))
{
ES0 = 1; // Enables UART interrupts
REN0 = 1; // Enables UART receives
CR = 0; // Disables PCA0 counter
EIE1 &= ~0x10; // Disable PCA0 interrupts
CCF0 = 0;
// These statements reset counter variables and registers
oldvalue = 0;
PCA0CP0 = 0;
EDGES_THIS_SESSION = 0;
preamble_count = 0;
}
}
}
else // RX_STATEMACHINE == UNCALIBRATED
// This code runs once, after ASLEEP exits, the first time the system
// gets set to RX mode. It looks for a preamble and sets the
// transceiver's averaging filter after enough preamble bits have been
// received.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -