📄 si47xxfmrx.c
字号:
// Inputs:
// frequency: frequency in 10kHz steps
//
// Returns:
// The RSSI level found during the tune.
//-----------------------------------------------------------------------------
u8 si47xxFMRX_tune(u16 frequency)
{
// Enable the bit used for the interrupt of STC.
SeekTuneInProc = 1;
// Call the tune command to start the tune.
WaitSTCInterrupt = 1;
fmTuneFreq(frequency);
// wait for the interrupt before continuing
// If you do not wish to use interrupts but wish to poll the part
// then comment out this line.
while (WaitSTCInterrupt); // Wait for interrupt to clear the bit
// Wait for stc bit to be set
while (!(getIntStatus() & STCINT));
// Clear the STC bit and get the results of the tune.
fmTuneStatus(0, 1);
// Disable the bit used for the interrupt of STC.
SeekTuneInProc = 0;
// Return the RSSI level
return RSSI;
}
//-----------------------------------------------------------------------------
// Inputs:
// seekup: 0 = seek down
// 1 = seek up
// seekmode: 0 = wrap at band limits
// 1 = stop at band limits
// Outputs:
// zero = seek found a station
// nonzero = seek did not find a station
//-----------------------------------------------------------------------------
u8 si47xxFMRX_seek(u8 seekup, u8 seekmode)
{
// Enable the bit used for the interrupt of STC.
SeekTuneInProc = 1;
// Call the tune command to start the seek.
WaitSTCInterrupt = 1;
fmSeekStart(seekup, !seekmode);
// wait for the interrupt before continuing
// If you do not wish to use interrupts but wish to poll the part
// then comment out these two lines.
while (WaitSTCInterrupt); // Wait for interrupt to clear the bit
// Wait for stc bit to be set
// If there is a display to update seek progress, then you could
// call fmTuneStatus in this loop to get the current frequency.
// When calling fmTuneStatus here make sure intack is zero.
while (!(getIntStatus() & STCINT));
// Clear the STC bit and get the results of the tune.
fmTuneStatus(0, 1);
// Disable the bit used for the interrupt of STC.
SeekTuneInProc = 0;
// The tuner is now set to the newly found channel if one was available
// as indicated by the seek-fail bit.
return BLTF; //return seek fail indicator
}
//-----------------------------------------------------------------------------
// Returns the current tuned frequency of the part
//
// Returns:
// frequency in 10kHz steps
//-----------------------------------------------------------------------------
u16 si47xxFMRX_get_frequency()
{
// Get the tune status which contains the current frequency
fmTuneStatus(0, 0);
// Return the frequency
return Freq;
}
//-----------------------------------------------------------------------------
// Returns the current tuned frequency of the part
//
// Returns:
// frequency in 10kHz steps
//-----------------------------------------------------------------------------
u8 si47xxFMRX_get_rssi()
{
// Get the tune status which contains the current frequency
fmRsqStatus(0);
// Return the RSSI level
return RSSI;
}
//-----------------------------------------------------------------------------
// Quickly tunes to the passed frequency, checks the power level and snr,
// and returns
//
// Inputs:
// Channel number in 10kHz steps
//
// Output:
// The RSSI level after tune
//-----------------------------------------------------------------------------
u8 quickAFTune(u16 freq)
{
u16 current_freq = 0;
u8 current_rssi = 0;
// Get the current frequency from the part
fmTuneStatus(0, 0);
current_freq = Freq;
// Tune to the AF frequency, check the RSSI, tune back
current_rssi = si47xxFMRX_tune(freq);
// Return to the original channel
si47xxFMRX_tune(current_freq);
return current_rssi;
}
//-----------------------------------------------------------------------------
// Helper function that sends the FM_TUNE_FREQ command to the part
//
// Inputs:
// frequency in 10kHz steps
//-----------------------------------------------------------------------------
static void fmTuneFreq(u16 frequency)
{
// Put the ID for the command in the first byte.
cmd[0] = FM_TUNE_FREQ;
// Initialize the reserved section to 0
cmd[1] = 0;
// Put the frequency in the second and third bytes.
cmd[2] = (u8)(frequency >> 8);
cmd[3] = (u8)(frequency & 0x00FF);
// Set the antenna calibration value.
cmd[4] = (u8)0; // Auto
// Invoke the command
si47xx_command(5, cmd, 1, rsp);
}
//-----------------------------------------------------------------------------
// Helper function that sends the FM_SEEK_START command to the part
//
// Inputs:
// seekUp: If non-zero seek will increment otherwise decrement
// wrap: If non-zero seek will wrap around band limits when hitting the end
// of the band limit.
//-----------------------------------------------------------------------------
static void fmSeekStart(u8 seekUp, u8 wrap)
{
// Put the ID for the command in the first byte.
cmd[0] = FM_SEEK_START;
// Put the flags if the bit was set for the input parameters.
cmd[1] = 0;
if(seekUp) cmd[1] |= FM_SEEK_START_IN_SEEKUP;
if(wrap) cmd[1] |= FM_SEEK_START_IN_WRAP;
// Invoke the command
si47xx_command(2, cmd, 1, rsp);
}
//-----------------------------------------------------------------------------
// Helper function that sends the FM_TUNE_STATUS command to the part
//
// Inputs:
// cancel: If non-zero the current seek will be cancelled.
// intack: If non-zero the interrupt for STCINT will be cleared.
//
// Outputs: // These are global variables and are set by this method
// STC: The seek/tune is complete
// BLTF: The seek reached the band limit or original start frequency
// AFCRL: The AFC is railed if this is non-zero
// Valid: The station is valid if this is non-zero
// Freq: The current frequency
// RSSI: The RSSI level read at tune.
// ASNR: The audio SNR level read at tune.
// AntCap: The current level of the tuning capacitor.
//-----------------------------------------------------------------------------
static void fmTuneStatus(u8 cancel, u8 intack)
{
// Put the ID for the command in the first byte.
cmd[0] = FM_TUNE_STATUS;
// Put the flags if the bit was set for the input parameters.
cmd[1] = 0;
if(cancel) cmd[1] |= FM_TUNE_STATUS_IN_CANCEL;
if(intack) cmd[1] |= FM_TUNE_STATUS_IN_INTACK;
// Invoke the command
si47xx_command(2, cmd, 8, rsp);
// Parse the results
STC = !!(rsp[0] & STCINT);
BLTF = !!(rsp[1] & FM_TUNE_STATUS_OUT_BTLF);
AFCRL = !!(rsp[1] & FM_TUNE_STATUS_OUT_AFCRL);
Valid = !!(rsp[1] & FM_TUNE_STATUS_OUT_VALID);
Freq = ((u16)rsp[2] << 8) | (u16)rsp[3];
RSSI = rsp[4];
ASNR = rsp[5];
AntCap = rsp[7];
}
//-----------------------------------------------------------------------------
// Helper function that sends the FM_RSQ_STATUS command to the part
//
// Inputs:
// intack: If non-zero the interrupt for STCINT will be cleared.
//
// Outputs:
// Status: Contains bits about the status returned from the part.
// RsqInts: Contains bits about the interrupts that have fired related to RSQ.
// SMUTE: The soft mute function is currently enabled
// AFCRL: The AFC is railed if this is non-zero
// Valid: The station is valid if this is non-zero
// Pilot: A pilot tone is currently present
// Blend: Percentage of blend for stereo. (100 = full stereo)
// RSSI: The RSSI level read at tune.
// ASNR: The audio SNR level read at tune.
// FreqOff: The frequency offset in kHz of the current station from the tuned
// frequency.
//-----------------------------------------------------------------------------
static void fmRsqStatus(u8 intack)
{
// Put the ID for the command in the first byte.
cmd[0] = FM_RSQ_STATUS;
// Put the flags if the bit was set for the input parameters.
cmd[1] = 0;
if(intack) cmd[1] |= FM_RSQ_STATUS_IN_INTACK;
// Invoke the command
si47xx_command(2, cmd, 8, rsp);
// Parse the results
Status = rsp[0];
RsqInts = rsp[1];
SMUTE = !!(rsp[2] & FM_RSQ_STATUS_OUT_SMUTE);
AFCRL = !!(rsp[2] & FM_RSQ_STATUS_OUT_AFCRL);
Valid = !!(rsp[2] & FM_RSQ_STATUS_OUT_VALID);
Pilot = !!(rsp[3] & FM_RSQ_STATUS_OUT_PILOT);
Blend = rsp[3] & FM_RSQ_STATUS_OUT_STBLEND;
RSSI = rsp[4];
ASNR = rsp[5];
FreqOff = rsp[7];
}
//-----------------------------------------------------------------------------
// Helper function that sends the FM_RDS_STATUS command to the part
//
// Inputs:
// intack: If non-zero the interrupt for STCINT will be cleared.
// mtfifo: If non-zero the fifo will be cleared.
//
// Outputs:
// Status: Contains bits about the status returned from the part.
// RdsInts: Contains bits about the interrupts that have fired related to RDS.
// RdsSync: If non-zero the RDS is currently synced.
// GrpLost: If non-zero some RDS groups were lost.
// RdsFifoUsed: The amount of groups currently remaining in the RDS fifo.
// BlockA: Block A group data from the oldest FIFO entry.
// BlockB: Block B group data from the oldest FIFO entry.
// BlockC: Block C group data from the oldest FIFO entry.
// BlockD: Block D group data from the oldest FIFO entry.
// BleA: Block A corrected error information.
// BleB: Block B corrected error information.
// BleC: Block C corrected error information.
// BleD: Block D corrected error information.
//-----------------------------------------------------------------------------
void fmRdsStatus(u8 intack, u8 mtfifo)
{
// Put the ID for the command in the first byte.
cmd[0] = FM_RDS_STATUS;
// Put the flags if the bit was set for the input parameters.
cmd[1] = 0;
if(intack) cmd[1] |= FM_RDS_STATUS_IN_INTACK;
if(mtfifo) cmd[1] |= FM_RDS_STATUS_IN_MTFIFO;
// Invoke the command
si47xx_command(2, cmd, 13, rsp);
// Parse the results
Status = rsp[0];
RdsInts = rsp[1];
RdsSync = !!(rsp[2] & FM_RDS_STATUS_OUT_SYNC);
GrpLost = !!(rsp[2] & FM_RDS_STATUS_OUT_GRPLOST);
RdsFifoUsed = rsp[3];
BlockA = ((u16)rsp[4] << 8) | (u16)rsp[5];
BlockB = ((u16)rsp[6] << 8) | (u16)rsp[7];
BlockC = ((u16)rsp[8] << 8) | (u16)rsp[9];
BlockD = ((u16)rsp[10] << 8) | (u16)rsp[11];
BleA = (rsp[12] & FM_RDS_STATUS_OUT_BLEA) >> FM_RDS_STATUS_OUT_BLEA_SHFT;
BleB = (rsp[12] & FM_RDS_STATUS_OUT_BLEB) >> FM_RDS_STATUS_OUT_BLEB_SHFT;
BleC = (rsp[12] & FM_RDS_STATUS_OUT_BLEC) >> FM_RDS_STATUS_OUT_BLEC_SHFT;
BleD = (rsp[12] & FM_RDS_STATUS_OUT_BLED) >> FM_RDS_STATUS_OUT_BLED_SHFT;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -