📄 rds.c
字号:
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <c8051f320.h>
#include <stddef.h>
#include "typedefs.h"
#include "example.h"
sbit LED = P1^5;
//-----------------------------------------------------------------------------
// 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 BLER_SCALE_MAX 200 // Block Errors are reported in .5% increments
//-----------------------------------------------------------------------------
// Globals
//-----------------------------------------------------------------------------
// 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;
// RDS Program Identifier
u16 xdata piDisplay; // Displayed Program Identifier
// RDS Program Type
u8 xdata ptyDisplay; // Displayed Program Type
// RDS Radio Text
u8 xdata rtDisplay[64]; // 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 = 0; // Radio Text A/B flag
static bit rtFlagValid = 0; // 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 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
// Debug information storing number of each kind of group received
u16 xdata debug_group_counters[32];
//-----------------------------------------------------------------------------
// Function prototypes
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
void
initRds(void)
{
u8 i;
// Reset RDS variables
RdsDataAvailable = 0;
RdsDataLost = 0;
RdsIndicator = 0;
RdsBlocksValid = 0;
RdsBlocksTotal = 0;
// Clear Radio Text
rtFlagValid = 0;
for (i=0; i<sizeof(rtDisplay); i++)
{
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++)
{
debug_group_counters[i] = 0;
}
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
#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;
}
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
#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)
{
// The new byte is a match with the low probability byte. Swap
// them, reset the counter and flag the text as in transition.
// Note that the counter for this character goes higher than
// the validation limit because it will get knocked down later
psCnt[addr] = PS_VALIDATE_LIMIT + 1;
psTmp1[addr] = psTmp0[addr];
psTmp0[addr] = byte;
textChange = 1;
}
else if(!psCnt[addr+i])
{
// The new byte is replacing an empty byte in the high
// proability array
psTmp0[addr] = byte;
psCnt[addr] = 1;
}
else
{
// The new byte doesn't match anything, put it in the
// low probablity array.
psTmp1[addr] = byte;
}
if(textChange)
{
// When the text is changing, decrement the count for all
// characters to prevent displaying part of a message
// that is in transition.
for(i=0;i<sizeof(psCnt);i++)
{
if(psCnt[i] > 1)
{
psCnt[i]--;
}
}
}
// The PS text is incomplete if any character in the high
// probability array has been seen fewer times than the
// validation limit.
for (i=0;i<sizeof(psTmp0);i++)
{
if(psCnt[i] < PS_VALIDATE_LIMIT)
{
psComplete = 0;
break;
}
}
// If the PS text in the high probability array is complete
// copy it to the display array
if (psComplete)
{
for (i=0;i<sizeof(psDisplay); i++)
{
psDisplay[i] = psTmp0[i];
}
}
}
//-----------------------------------------------------------------------------
// The basic implementation of the Radio Text update displays data
// immediately but does no additional error detection.
//-----------------------------------------------------------------------------
static void
update_rt_basic(bit abFlag, u8 count, u8 addr, u8* chars)
{
bit complete = 1;
u8 i,j;
// If the A/B flag changes, wipe out the text
if ((abFlag != rtFlag) && rtFlagValid)
{
for (i=0;i<sizeof(rtDisplay);i++)
{
rtTmp0[i] = 0;
}
}
rtFlag = abFlag; // Save the A/B flag
rtFlagValid = 1; // Now the A/B flag is valid
for (i=0; i<count; i++)
{
// Store the data in our temporary array
rtTmp0[addr+i] = chars[i];
if(chars[i] == 0x0d)
{
// The end of message character has been received.
// Wipe out the rest of the text.
for (j=addr+i+1;j<sizeof(rtDisplay);j++)
{
rtTmp0[j] = 0;
}
break;
}
}
// A message is complete if all the characters preceeding 0x0d (or last
// character in the array) are non-null
for (i=0;i<sizeof(rtTmp0);i++)
{
if(!rtTmp0[i])
{
complete = 0;
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -