📄 si470x.c
字号:
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <c8051f320.h>
#include <stddef.h>
#include "typedefs.h"
#include "example.h"
//-----------------------------------------------------------------------------
// Defines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------
sbit RSTB = P1^3;
sbit SENB = P1^2;
sbit SCLK = P1^1;
sbit SDIO = P0^7;
//-----------------------------------------------------------------------------
// Function prototypes
//-----------------------------------------------------------------------------
static u16 chanToFreq (u16 channel);
static u16 freqToChan (u16 frequency);
//-----------------------------------------------------------------------------
// Take the Si470x out of powerdown mode, initializes a set
// of shadow registers, and sets some default register values.
//-----------------------------------------------------------------------------
void si470x_initialize (void)
{
u8 i;
// zero shadow registers to start
for (i=0; i<16; i++)
si470x_shadow[i] = 0;
si470x_shadow[2] = 0x0001; // set enable bit
si470x_reg_write(2, 2);
// set default parameters
si470x_shadow[ 4] = 0xd004; // Enable interrupt generation, enable rds, set de-emphasis
// set gpio muxes. gpio2 generates an interrupt
si470x_shadow[ 5] &= 0x00ff; // set seek threshold
si470x_shadow[ 5] |= 0x1400;
si470x_reg_write(4, 5);
wait_ms(85); // wait for si470x to powerup
si470x_reg_read(10, 9); // initialize shadow registers
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void si470x_powerup (void)
{
si470x_reg_write(2, 2); // restore register 2 to power up again
wait_ms(85); // wait for si470x to powerup
si470x_tune(0); // retune to last station
}
//-----------------------------------------------------------------------------
// Set the volume and mute/unmute status
//
// Inputs:
// volume: a 4-bit volume value
// dmute: 0 = output muted
// 1 = output enabled (mute disabled)
//
//-----------------------------------------------------------------------------
void si470x_set_volume (u8 volume, u8 dmute)
{
if (dmute)
si470x_shadow[2] |= 0x4000;
else
si470x_shadow[2] &= ~0x4000;
si470x_shadow[5] &= ~0x000F;
si470x_shadow[5] |= volume & 0x000F;
si470x_reg_write(2, 5);
}
//-----------------------------------------------------------------------------
// Forces mono mode or enables stereo mode
//
// Inputs:
// mono: 0 = stereo mode enabled
// 1 = mono mode forced
//-----------------------------------------------------------------------------
void si470x_set_mono(u8 mono)
{
if (mono)
si470x_shadow[2] |= 0x2000;
else
si470x_shadow[2] &= ~0x2000;
si470x_reg_write(2, 2);
}
//-----------------------------------------------------------------------------
// Tunes to a station number using the current band and spacing settings.
//
// Inputs:
// frequency: frequency in 10kHz steps
//
//-----------------------------------------------------------------------------
void si470x_tune (u16 frequency)
{
// write channel number to register 0x03 and set tune bit
// if frequency is zero, routine will retune to last station (used for powerup)
if (frequency)
si470x_shadow[ 3] = freqToChan(frequency) | 0x8000;
else
si470x_shadow[ 3] |= freqToChan(frequency) | 0x8000;
si470x_reg_write(3, 3);
// wait for stc bit to be set
do {
si470x_reg_read(10, 10);
} while ((si470x_shadow[10] & 0x4000) == 0);
// write address 0x03 to clear tune bit
si470x_shadow[ 3] &= ~0x8000;
si470x_reg_write(3, 3);
// wait for stc bit to be cleared
do {
si470x_reg_read(10, 10);
} while ((si470x_shadow[10] & 0x4000) != 0);
// read adresses 0x0a - 0x0b to read status (optional)
// Address 0x0a just read, so just read 0x0b here
si470x_reg_read(11, 11); // update shadow registers
}
//-----------------------------------------------------------------------------
// Inputs:
// seekup: 0 = seek down
// 1 = seek up
//
// Outputs:
// zero = seek found a station
// nonzero = seek did not find a station
//
//-----------------------------------------------------------------------------
u8 si470x_seek (u8 seekup)
{
// set or clear seekup bit in address 0x02
if (seekup)
si470x_shadow[ 2] |= 0x0200;
else
si470x_shadow[ 2] &= ~0x0200;
// set seek bit in address 0x02
si470x_shadow[ 2] |= 0x0100;
si470x_reg_write(2, 2);
// wait for stc bit to be set
do {
si470x_reg_read(10, 10);
} while ((si470x_shadow[10] & 0x4000) == 0);
// clear seek bit in address 0x02
si470x_shadow[ 2] &= ~0x0100;
si470x_reg_write(2, 2);
// wait for stc bit to be cleared
do {
si470x_reg_read(10, 10);
} while ((si470x_shadow[10] & 0x4000) != 0);
// read adresses 0x0a - 0x0b to read status (optional)
// Address 0x0a just read, so just read 0x0b here
si470x_reg_read(11, 11); // update shadow registers
return (si470x_shadow[10]&0x2000); //return seek fail indicator
}
//-----------------------------------------------------------------------------
// Outputs:
// returns current channel number in a format that can be
// used as parameter in to tune or chan2freq
//
//-----------------------------------------------------------------------------
u16 si470x_get_frequency(void)
{
return (chanToFreq(si470x_shadow[11] & 0x03ff));
}
//-----------------------------------------------------------------------------
// Outputs:
// returns current rssi value
//
//-----------------------------------------------------------------------------
u8 si470x_get_rssi(void)
{
si470x_reg_read(10, 10); // update shadow registers
return ((u8)(si470x_shadow[10]&0xff));
}
//-----------------------------------------------------------------------------
// Returns rssi and stereo indicator in one word
//
// Outputs:
// returns current rssi value and stereo indicators
// bit 8 = Stereo indicator
// bits 7:0 = rssi
//
//-----------------------------------------------------------------------------
u16 si470x_get_rssi_and_stereo(void)
{
si470x_reg_read(10, 10); // update shadow registers
return ((u8)(si470x_shadow[10]&0x1ff));
}
//-----------------------------------------------------------------------------
// Converts from a frequency value to a channel number
//
// Inputs:
// frequency in 10kHz steps
//
// Output:
// channel number using current channel spacing
//
//-----------------------------------------------------------------------------
static u16 freqToChan (u16 frequency)
{
u16 channelSpacing;
u16 bottomOfBand;
u16 channel;
if ((si470x_shadow[5] & 0x0080) == 0x0000)
bottomOfBand = 8750;
else
bottomOfBand = 7600;
if (frequency < bottomOfBand)
frequency = bottomOfBand;
if ((si470x_shadow[5] & 0x0030) == 0x0000)
channelSpacing = 20;
else if ((si470x_shadow[5] & 0x0030) == 0x0010)
channelSpacing = 10;
else
channelSpacing = 5;
channel = (frequency - bottomOfBand) / channelSpacing;
return (channel);
}
//-----------------------------------------------------------------------------
// Converts from a channel number to a frequency value
//
// Inputs:
// Channel number using current channel spacing
//
// Output:
// Frequency in 10kHz steps
//
//-----------------------------------------------------------------------------
static u16 chanToFreq (u16 channel) {
u16 channelSpacing;
u16 bottomOfBand;
u16 frequency;
// calculate frequency
if ((si470x_shadow[5] & 0x0080) == 0x0000)
bottomOfBand = 8750;
else
bottomOfBand = 7600;
if ((si470x_shadow[5] & 0x0030) == 0x0000)
channelSpacing = 20;
else if ((si470x_shadow[5] & 0x0030) == 0x0010)
channelSpacing = 10;
else
channelSpacing = 5;
frequency = bottomOfBand + channelSpacing * channel;
return (frequency);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -