?? f360_cc1100.c
字號:
// P1.3 - Audio Input
// P1.4 - Test Point
// P1.5 - LED1
// P1.6 - LED2
// P1.7 - Switch
void PORT_Init (void)
{
P0SKIP = 0xFF; // skip all port 0 pins
P1SKIP = 0x08; // skip ADC input P1.3
P1MDIN &= ~0x08; // set P0.0 to analog input
P0MDOUT |= 0x4C; // set P0.2, P0.3, P0.6 to push-pull
P1MDOUT |= 0x68; // Audio input, debug pins
RouteSPI(); // routes SPI pins to port pins
XBR1 |= 0x40; // Enable crossbar, CEX0 at port pin
}
//-----------------------------------------------------------------------------
// 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 = 0x00; // Master disable, CKPOL = 0
SPI0CN = 0; // clear all flags
IE |= 0x40; // enable SPI interrupts
SPIEN = 0; // leave SPI disabled
IP |= 0x40; // make SPI ISR high priority
}
//-----------------------------------------------------------------------------
// 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 3 Overflows
IDA0CN |= 0x80; // Enable DAC
}
//
//-----------------------------------------------------------------------------
// PCA0_Init
//-----------------------------------------------------------------------------
//
// The PCA is used to watch for the edges of the Sync Word at the SPI MOSI pin.
// Module 0 is configured for edge-triggered captures, and count sysclocks.
// PCA interrupts are enabled. Leaves PCA disabled.
//
void PCA0_Init(void)
{
PCA0CPM0 = 0x42; // set PCA0 to edge-triggered capture
// mode
PCA0MD |= 4<<1; // Set PCA0 to count sys clocks
CR = 1; // enable PCA0 timer
}
//----------------------------------------------------------------------------
// Timer2_Init
//----------------------------------------------------------------------------
//
// Timer 2 is used as the start of conversion clock source for the ADC,
// and controls the audio sampling rate.
//
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. Timer 3 controls
// the DAC output rate.
//
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
}
//-----------------------------------------------------------------------------
// Variables_Init
//-----------------------------------------------------------------------------
//
void Variables_Init(void)
{
Audio_LocalState = Audio_Quiet;
Audio_RemoteState = Audio_Quiet;
CLEAR_FIFOS();
}
//-----------------------------------------------------------------------------
// 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
{
signed short SampleDifference; // stores difference between current
// and previous ADC0 values
static short OldADCValue; // previous ADC value
static short NewADCValue; // newest ADC value
static unsigned short AudioStateThreshold;
// stores number of consecutive audio
// bytes that have fallen outside
// the defined threshold used to
// determine if the audio state should
// switch from "quiet" to "loud" or
// "loud" to "quiet"
static unsigned char TableIndex = 0;// index into sine table
AD0INT = 0; // acknowledge end-of-conversion
// interrupt
OldADCValue = NewADCValue; // save old ADC value
NewADCValue = ADC0 - 512; // add bias to new ADC value
// if the button on AN147's PCB has been pressed, add a sine wave to the
// the audio input signal
if(!SW2)
{
TableIndex += 1; // increment sine table index value
if(TableIndex >= 32) TableIndex = 0;
// step through 16-element 1/2 period
// sine table twice to produce a sine
// wave's complete period
// conditional adjusts the sine wave so that the first cycle
// through the sine table produces the half of the period with values
// higher than 0, and the second cycle produces values less than 0
// Also, amplifies the sine wave by shifting the index value to the
// left, which is equivalent to a gain of 2
if(TableIndex < 16)
NewADCValue += (unsigned char)(Audio_SineTable[TableIndex] << 1);
else
NewADCValue -= (unsigned char)(Audio_SineTable[TableIndex - 16]) << 1;
}
// This section of the ADC0 ISR determines whether the signal present at the
// audio input should be considered "loud" or "quiet"
SampleDifference = (signed)OldADCValue - (signed)NewADCValue;
// measure whether difference between the current sample and the
// last sample is greater than the threshold value <Audio_QuietThreshold>
if( (SampleDifference > (signed)Audio_QuietThreshold) ||
(SampleDifference < (-(signed)Audio_QuietThreshold)) )
{
if(Audio_LocalState == Audio_Quiet)
{
// add one to accumulator and check to see if
// the critical accumulator value has been reached
if(AudioStateThreshold++ == AudioStateQuietToLoud)
{
Audio_LocalState = Audio_Loud;
AudioStateThreshold = 0;
}
}
else if(Audio_LocalState == Audio_Loud)
{
// reset accumulator
AudioStateThreshold = 0;
}
}
// else <SampleDifference> is below the threshold value
else
{
if(Audio_LocalState == Audio_Quiet)
{
if(AudioStateThreshold > 0)
{
AudioStateThreshold--;
}
}
else if(Audio_LocalState == Audio_Loud)
{
// add one to accumulator and check to see if
// the critical accumulator value has been reached
if(AudioStateThreshold++ == AudioStateLoudToQuiet)
{
Audio_LocalState = Audio_Quiet;
AudioStateThreshold = 0;
}
}
}
ADCRXFIFO_Push(NewADCValue); // save ADC value for compression
}
//-----------------------------------------------------------------------------
// Timer3_ISR
//-----------------------------------------------------------------------------
// This ISR updates the DAC output at a rate of DACUPDATERATE. It also
// fetches the most recently captured local ADC sample, attenuates the sample,
// and adds the signal to the DAC output for a loop back.
//
void TIMER3_ISR(void) interrupt 14
{
static unsigned short new_value;
USHORT tempvalue;
TMR3CN &= ~0xC0; // acknowledge interrupt
if (!DACTXFIFO_EMPTY) // if new DAC data is available,
{ // update output information
new_value = DACTXFIFO_Pull();
// only play received audio if the remote endpoint as determined
// that the audio is of audible amplitude
if(Audio_RemoteState == Audio_Loud)
{
// DAC output must be left-justified, and loaded
// low byte first
tempvalue.S = new_value;
// tempvalue.S = tempvalue.S + ADCRXFIFO_Newest()>>4;
tempvalue.S = tempvalue.S << 6;
IDA0L = tempvalue.C[1];
IDA0H = tempvalue.C[0];
}
}
}
//-----------------------------------------------------------------------------
// PCA0_ISR
//-----------------------------------------------------------------------------
//
// The PCA ISR is used to synchronize with the data stream from
// the CC1100 along byte boundaries using the Sync Word 0xFFFFEE.
// The PCA is set to interrupt on the falling edge of the DIO line.
// When the interrupt gets requested, the PCA ISR will spin while it
// looks for another rising edge. Upon finding the second rising edge,
// the PCA will disable itself, route SPI back to the port pins, and
// enable the SPI interface.
//
void PCA0_ISR(void) interrupt 11
{
if(CCF0)
{
// acknowledge interrupt
CCF0 = 0;
// wait until rising edge after first received '0' in Sync Word stream
while(!DIO);
_nop_();
// wait until falling edge of second '0' in stream
while(DIO);
_nop_();
// wait for rising edge in DCLK
while(!DCLK);
_nop_();
// wait for falling edge
while(DCLK);
// route SPI back to port pins
RouteSPI();
EIE1 &= ~0x10; // Disable PCA0 interrupts
PCA0CPM0 = 0x42; // set to 8-bit PWM output
SPIF = 0; // clear pending interrupt flag
SPIEN = 1; // re-enable SPI
}
else if(CCF1)
{
}
else if(CCF2)
{
}
}
//-----------------------------------------------------------------------------
// SPI_ISR
//-----------------------------------------------------------------------------
//
// SPI ISR contains the RF state machine. An interrupt will be requested
// after 8 bits of data have been shifted out to or in from the RF
// transceiver. Progress through the state machine is gated by byte counters
// that increment once per interrupt servicing.
//
void SPI0_ISR(void) interrupt 6
{
static unsigned char PreambleByte; // counts Preamble bytes transmitted
static unsigned char SyncWordByte; // counts Sync Word bytes transmitted
unsigned char SPI_Input; // saves the received byte acquired
// from SPI0DAT
SPI_Input = SPI0DAT;
// test for all SPI error conditions
if(SPI0CN & 0x70)
{
SPI0CN &= ~0x70; // acknowledge error conditions, clear
// flags
}
// bit is set inside RF state machine initialization routines
if(RXTX_ResetVariables)
{
RXTX_ResetVariables = FALSE; // clear flag
RXTX_NoPreambleCount = 0; // reset all counters
PreambleByte = 0;
SyncWordByte = 0;
}
if(SPIF)
{
SPIF = 0; // acknowledge interrupt
switch(RXTX_StateMachine)
{
case(RX_SearchForMaster):
// if received byte is Preamble, take appropriate action
if((SPI0DAT == 0x55) || (SPI0DAT == 0xAA))
{
if(++PreambleByte == RX_MinBytesInitPreamble)
{
RXTX_StateMachine = RX_SyncWord;
// timer will synchronize with master's at the end
// of the first received data packet
SPI_TimerEnable = TRUE;
SPI_Timer = SPI_SlopTimeOut + TX_NumBytesPreamble;
RXTX_MasterSelect = RXTX_Slave;
// reset counter
PreambleByte = 0;
}
}
else // received byte was not Preamble
{
// reset counter
PreambleByte = 0;
}
break;
case(RX_Preamble):
{
if(!SPI_TimeOutEvent)
{
// of byte received is Preamble, increment counter
if((SPI0DAT == 0x55) || (SPI0DAT == 0xAA))
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -