📄 fmrxrds.c
字号:
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <stddef.h>
#include "c8051f320.h"
#include "typedefs.h"
#include "portdef.h"
#include "FMRXrds.h"
#include "si47xxFMRX.h"
//-----------------------------------------------------------------------------
// local defines
//-----------------------------------------------------------------------------
#define RDS_TYPE_0A ( 0 * 2 + 0)
#define RDS_TYPE_0B ( 0 * 2 + 1)
#define RDS_TYPE_1A ( 1 * 2 + 0)
#define RDS_TYPE_1B ( 1 * 2 + 1)
#define RDS_TYPE_2A ( 2 * 2 + 0)
#define RDS_TYPE_2B ( 2 * 2 + 1)
#define RDS_TYPE_3A ( 3 * 2 + 0)
#define RDS_TYPE_3B ( 3 * 2 + 1)
#define RDS_TYPE_4A ( 4 * 2 + 0)
#define RDS_TYPE_4B ( 4 * 2 + 1)
#define RDS_TYPE_5A ( 5 * 2 + 0)
#define RDS_TYPE_5B ( 5 * 2 + 1)
#define RDS_TYPE_6A ( 6 * 2 + 0)
#define RDS_TYPE_6B ( 6 * 2 + 1)
#define RDS_TYPE_7A ( 7 * 2 + 0)
#define RDS_TYPE_7B ( 7 * 2 + 1)
#define RDS_TYPE_8A ( 8 * 2 + 0)
#define RDS_TYPE_8B ( 8 * 2 + 1)
#define RDS_TYPE_9A ( 9 * 2 + 0)
#define RDS_TYPE_9B ( 9 * 2 + 1)
#define RDS_TYPE_10A (10 * 2 + 0)
#define RDS_TYPE_10B (10 * 2 + 1)
#define RDS_TYPE_11A (11 * 2 + 0)
#define RDS_TYPE_11B (11 * 2 + 1)
#define RDS_TYPE_12A (12 * 2 + 0)
#define RDS_TYPE_12B (12 * 2 + 1)
#define RDS_TYPE_13A (13 * 2 + 0)
#define RDS_TYPE_13B (13 * 2 + 1)
#define RDS_TYPE_14A (14 * 2 + 0)
#define RDS_TYPE_14B (14 * 2 + 1)
#define RDS_TYPE_15A (15 * 2 + 0)
#define RDS_TYPE_15B (15 * 2 + 1)
#define CORRECTED_NONE 0
#define CORRECTED_ONE_TO_TWO 1
#define CORRECTED_THREE_TO_FIVE 2
#define UNCORRECTABLE 3
#define ERRORS_CORRECTED(data,block) ((data>>block)&0x03)
#define BLER_SCALE_MAX 200 // Block Errors are reported in .5% increments
//-----------------------------------------------------------------------------
// Globals
//-----------------------------------------------------------------------------
u8 xdata RdsReadPtr;
u8 xdata RdsWritePtr;
bit RdsFifoEmpty;
// Determines if the basic or advanced PS/RT RDS display functions are used
// The basic functions are closely tied to the recommendations in the RBDS
// specification and are faster to update but more error prone. The advanced
// functions attempt to detect errors and only display complete messages
static bit rdsBasic = 0;
bit Gpio2StickyBit = 0;
// RDS Program Identifier
u16 xdata piDisplay; // Displayed Program Identifier
// RDS Program Type
u8 xdata ptyDisplay; // Displayed Program Type
bit firstInitDone;
u8 xdata rdsBlerMax[4];
// RDS Radio Text
u8 xdata rtDisplay[64]; // Displayed Radio Text
u8 xdata rtSimple[64]; // Simple Displayed Radio Text
static u8 xdata rtTmp0[64]; // Temporary Radio Text (high probability)
static u8 xdata rtTmp1[64]; // Temporary radio text (low probability)
static u8 xdata rtCnt[64]; // Hit count of high probabiltiy radio text
static bit rtFlag; // Radio Text A/B flag
static bit rtFlagValid; // Radio Text A/B flag is valid
static bit rtsFlag; // Radio Text A/B flag
static bit rtsFlagValid; // Radio Text A/B flag is valid
// RDS Program Service
u8 xdata psDisplay[8]; // Displayed Program Service text
static u8 xdata psTmp0[8]; // Temporary PS text (high probability)
static u8 xdata psTmp1[8]; // Temporary PS text (low probability)
static u8 xdata psCnt[8]; // Hit count of high probability PS text
// RDS Clock Time and Date
bit ctDayHigh; // Modified Julian Day high bit
u16 xdata ctDayLow; // Modified Julian Day low 16 bits
u8 xdata ctHour; // Hour
u8 xdata ctMinute; // Minute
i8 xdata ctOffset; // Local Time Offset from UTC
// RDS Alternate Frequency List
static u8 xdata afCount;
static u16 xdata afList[25];
// RDS flags and counters
u8 xdata RdsDataAvailable = 0; // Count of unprocessed RDS Groups
static u8 xdata RdsIndicator = 0; // If true, RDS was recently detected
static u16 xdata RdsDataLost = 0; // Number of Groups lost
static u16 xdata RdsBlocksValid = 0; // Number of valid blocks received
static u16 xdata RdsBlocksTotal = 0; // Total number of blocks expected
static u16 xdata RdsBlockTimer = 0; // Total number of blocks expected
static u16 xdata RdsGroupCounters[32]; // Number of each kind of group received
bit RdsSynchTimer = 0;
static u16 xdata RdsSynchValid = 0;
static u16 xdata RdsSynchTotal = 0;
static u16 xdata RdsGroupsTotal = 0;
static u16 xdata RdsGroups = 0;
static u16 xdata RdsValid[4];
bit rdsIgnoreAB;
//-----------------------------------------------------------------------------
// Function prototypes
//-----------------------------------------------------------------------------
void wait_ms(u16 ms);
static void updateRdsFifo(u16 * group, u8 errorFlags);
static void init_alt_freq(void);
//-----------------------------------------------------------------------------
// Externals
//-----------------------------------------------------------------------------
extern u8 xdata RdsInts;
extern u8 xdata RdsSync;
extern u8 xdata GrpLost;
extern u8 xdata RdsFifoUsed;
extern u16 xdata BlockA;
extern u16 xdata BlockB;
extern u16 xdata BlockC;
extern u16 xdata BlockD;
extern u8 xdata BleA;
extern u8 xdata BleB;
extern u8 xdata BleC;
extern u8 xdata BleD;
//-----------------------------------------------------------------------------
// After tuning to a new station, the RDS tracking variables need to be
// initialized.
//-----------------------------------------------------------------------------
void
initRdsVars(void)
{
u8 i;
// Set the maximum allowable errors in a block considered acceptable
// It's critical that block B be correct since it determines what's
// contained in the latter blocks. For this reason, a stricter tolerance
// is placed on block B
if (!firstInitDone)
{
rdsBlerMax[0] = CORRECTED_THREE_TO_FIVE; // Block A
rdsBlerMax[1] = CORRECTED_ONE_TO_TWO; // Block B
rdsBlerMax[2] = CORRECTED_THREE_TO_FIVE; // Block C
rdsBlerMax[3] = CORRECTED_THREE_TO_FIVE; // Block D
firstInitDone = 1;
}
// Reset RDS variables
RdsDataAvailable = 0;
RdsDataLost = 0;
RdsIndicator = 0;
RdsBlocksValid = 0;
RdsBlocksTotal = 0;
// Clear RDS Fifo
RdsFifoEmpty = 1;
RdsReadPtr = 0;
RdsWritePtr = 0;
// Clear Radio Text
rtFlagValid = 0;
rtsFlagValid = 0;
for (i=0; i<sizeof(rtDisplay); i++)
{
rtSimple[i] = 0;
rtDisplay[i] = 0;
rtTmp0[i] = 0;
rtTmp1[i] = 0;
rtCnt[i] = 0;
}
// Clear Program Service
for (i=0;i<sizeof(psDisplay);i++)
{
psDisplay[i] = 0;
psTmp0[i] = 0;
psTmp1[i] = 0;
psCnt[i] = 0;
}
// Reset Debug Group counters
for (i=0; i<32; i++)
{
RdsGroupCounters[i] = 0;
}
// Reset alternate frequency tables
init_alt_freq();
RdsSynchValid = 0;
RdsSynchTotal = 0;
RdsValid[0] = 0;
RdsValid[1] = 0;
RdsValid[2] = 0;
RdsValid[3] = 0;
RdsGroups = 0;
RdsGroupsTotal = 0;
ptyDisplay = 0;
piDisplay = 0;
ctDayHigh = 0;
ctDayLow = 0;
ctHour = 0;
ctMinute = 0;
ctOffset = 0;
}
//-----------------------------------------------------------------------------
// This routine adds an additional level of error checking on the PI code.
// A PI code is only considered valid when it has been identical for several
// groups.
//-----------------------------------------------------------------------------
#define RDS_PI_VALIDATE_LIMIT 4
static void
update_pi(u16 current_pi)
{
static u8 rds_pi_validate_count = 0;
static u16 rds_pi_nonvalidated;
// if the pi value is the same for a certain number of times, update
// a validated pi variable
if (rds_pi_nonvalidated != current_pi)
{
rds_pi_nonvalidated = current_pi;
rds_pi_validate_count = 1;
}
else
{
rds_pi_validate_count++;
}
if (rds_pi_validate_count > RDS_PI_VALIDATE_LIMIT)
{
piDisplay = rds_pi_nonvalidated;
}
}
//-----------------------------------------------------------------------------
// This routine adds an additional level of error checking on the PTY code.
// A PTY code is only considered valid when it has been identical for several
// groups.
//-----------------------------------------------------------------------------
#define RDS_PTY_VALIDATE_LIMIT 4
static void
update_pty(u8 current_pty)
{
static u8 xdata rds_pty_validate_count = 0;
static u8 xdata rds_pty_nonvalidated;
// if the pty value is the same for a certain number of times, update
// a validated pty variable
if (rds_pty_nonvalidated != current_pty)
{
rds_pty_nonvalidated = current_pty;
rds_pty_validate_count = 1;
}
else
{
rds_pty_validate_count++;
}
if (rds_pty_validate_count > RDS_PTY_VALIDATE_LIMIT)
{
ptyDisplay = rds_pty_nonvalidated;
}
}
//-----------------------------------------------------------------------------
// The basic implementation of the Program Service update displays data
// immediately but does no additional error detection.
//-----------------------------------------------------------------------------
static void
update_ps_basic(u8 current_ps_addr, u8 current_ps_byte)
{
psDisplay[current_ps_addr] = current_ps_byte;
}
//-----------------------------------------------------------------------------
// This implelentation of the Program Service update attempts to display
// only complete messages for stations who rotate text through the PS field
// in violation of the RBDS standard as well as providing enhanced error
// detection.
//-----------------------------------------------------------------------------
#define PS_VALIDATE_LIMIT 2
static void
update_ps(u8 addr, u8 byte)
{
u8 i;
bit textChange = 0; // indicates if the PS text is in transition
bit psComplete = 1; // indicates that the PS text is ready to be displayed
if(psTmp0[addr] == byte)
{
// The new byte matches the high probability byte
if(psCnt[addr] < PS_VALIDATE_LIMIT)
{
psCnt[addr]++;
}
else
{
// we have recieved this byte enough to max out our counter
// and push it into the low probability array as well
psCnt[addr] = PS_VALIDATE_LIMIT;
psTmp1[addr] = byte;
}
}
else if(psTmp1[addr] == byte)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -