-
Notifications
You must be signed in to change notification settings - Fork 91
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Date and time with MJD and example usage #38
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
/// | ||
/// \file SerialRadio.ino | ||
/// \file SerialRadio.ino | ||
/// \brief Radio implementation using the Serial communication. | ||
/// | ||
/// | ||
/// \author Matthias Hertel, http://www.mathertel.de | ||
/// \copyright Copyright (c) 2014 by Matthias Hertel.\n | ||
/// This work is licensed under a BSD style license.\n | ||
|
@@ -16,10 +16,10 @@ | |
/// ------ | ||
/// The necessary wiring of the various chips are described in the Testxxx example sketches. | ||
/// The boards have to be connected by using the following connections: | ||
/// | ||
/// | ||
/// Arduino port | SI4703 signal | RDA5807M signal | ||
/// :----------: | :-----------: | :-------------: | ||
/// GND (black) | GND | GND | ||
/// GND (black) | GND | GND | ||
/// 3.3V (red) | VCC | VCC | ||
/// 5V (red) | - | - | ||
/// A5 (yellow) | SCLK | SCLK | ||
|
@@ -76,15 +76,23 @@ int i_sidx = 5; ///< Start at Station with index=5 | |
/// by uncommenting the right radio object definition. | ||
|
||
// RADIO radio; ///< Create an instance of a non functional radio. | ||
RDA5807M radio; ///< Create an instance of a RDA5807 chip radio | ||
// SI4703 radio; ///< Create an instance of a SI4703 chip radio. | ||
// RDA5807M radio; ///< Create an instance of a RDA5807 chip radio | ||
SI4703 radio; ///< Create an instance of a SI4703 chip radio. | ||
//SI4705 radio; ///< Create an instance of a SI4705 chip radio. | ||
// TEA5767 radio; ///< Create an instance of a TEA5767 chip radio. | ||
|
||
|
||
/// get a RDS parser | ||
RDSParser rds; | ||
|
||
/// Modified Julian Day from RDS Time | ||
typedef struct MJD_INFO { | ||
int month; | ||
int day; | ||
int year; | ||
}; | ||
|
||
MJD_INFO mjd_info; | ||
|
||
/// State definition for this radio implementation. | ||
enum RADIO_STATE { | ||
|
@@ -100,7 +108,7 @@ RADIO_STATE state; ///< The state variable is used for parsing input characters. | |
|
||
|
||
|
||
/// Update the Frequency on the LCD display. | ||
/// Update the Frequency | ||
void DisplayFrequency(RADIO_FREQ f) | ||
{ | ||
char s[12]; | ||
|
@@ -109,13 +117,60 @@ void DisplayFrequency(RADIO_FREQ f) | |
} // DisplayFrequency() | ||
|
||
|
||
/// Update the ServiceName text on the LCD display. | ||
void DisplayServiceName(char *name) | ||
/// Update the ServiceName text | ||
void DisplayRDSServiceName(char *name) | ||
{ | ||
Serial.print("RDS:"); | ||
Serial.print("RDS ServiceName:"); | ||
Serial.println(name); | ||
} // DisplayServiceName() | ||
} // DisplayRDSServiceName() | ||
|
||
/// Update the text | ||
void DisplayRDSText(char *name) | ||
{ | ||
Serial.print("RDS Text:"); | ||
Serial.println(name); | ||
} // DisplayRDSText() | ||
|
||
/// Update the Date/Time | ||
void DisplayRDSTime(uint8_t hr, uint8_t mnt, uint32_t mjd, int8_t offset) | ||
{ | ||
Serial.print(" RDS Time: "); | ||
if (hr < 10) | ||
Serial.print('0'); | ||
Serial.print(hr); | ||
Serial.print(':'); | ||
if (mnt < 10) | ||
Serial.print('0'); | ||
Serial.print(mnt); | ||
Serial.print(" Offset: "); | ||
Serial.print(offset); | ||
|
||
getMJDInfo(mjd, &mjd_info); | ||
Serial.print(" Month: "); | ||
Serial.print(mjd_info.month); | ||
Serial.print(" Day: "); | ||
Serial.print(mjd_info.day); | ||
Serial.print(" Year: "); | ||
Serial.println(mjd_info.year); | ||
} // DisplayRDSTime() | ||
|
||
|
||
void getMJDInfo(uint32_t mjd, MJD_INFO *mjdInfo) | ||
{ | ||
int _year = (int)((mjd - 15078.2) / 365.25); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please avoid floating-point arithmetic. I hope you find a pure integer based solution. |
||
int _month = (int)((mjd - 14956.1 - (int)(_year * 365.25)) / 30.6001); | ||
int _day = (int)(mjd - 14956 - (int)(_year * 365.25) - (int)(_month * 30.6001)); | ||
int k = (_month == 14 || _month == 15) ? 1 : 0; | ||
|
||
_year = _year + k + 1900; | ||
_month = _month - 1 - k * 12; | ||
|
||
long WD = (long)((mjd + 2) % 7) + 1; //modulo 7 | Day of the Week | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WD is calculated by not used. can be removed or commented. |
||
|
||
mjdInfo->month = _month; | ||
mjdInfo->day = _day; | ||
mjdInfo->year = _year; | ||
} | ||
|
||
// - - - - - - - - - - - - - - - - - - - - - - - - - - | ||
|
||
|
@@ -216,7 +271,7 @@ void setup() { | |
Serial.print("Radio..."); | ||
delay(500); | ||
|
||
// Initialize the Radio | ||
// Initialize the Radio | ||
radio.init(); | ||
|
||
// Enable information to the Serial port | ||
|
@@ -237,7 +292,10 @@ void setup() { | |
|
||
// setup the information chain for RDS data. | ||
radio.attachReceiveRDS(RDS_process); | ||
rds.attachServicenNameCallback(DisplayServiceName); | ||
rds.attachServicenNameCallback(DisplayRDSServiceName); | ||
rds.attachTextCallback(DisplayRDSText); | ||
rds.attachTimeCallback(DisplayRDSTime); | ||
|
||
|
||
runSerialCommand('?', 0); | ||
} // Setup | ||
|
@@ -298,7 +356,7 @@ void loop() { | |
lastf = f; | ||
} // if | ||
nextFreqTime = now + 400; | ||
} // if | ||
} // if | ||
|
||
} // loop | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,12 +18,14 @@ | |
#define DEBUG_FUNC0(fn) { Serial.print(fn); Serial.println("()"); } | ||
|
||
/// Setup the RDS object and initialize private variables to 0. | ||
RDSParser::RDSParser() { | ||
RDSParser::RDSParser() | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here and in other places re re-formatting should be reversed to focus on the changes. |
||
memset(this, 0, sizeof(RDSParser)); | ||
} // RDSParser() | ||
|
||
|
||
void RDSParser::init() { | ||
void RDSParser::init() | ||
{ | ||
strcpy(_PSName1, "--------"); | ||
strcpy(_PSName2, _PSName1); | ||
strcpy(programServiceName, " "); | ||
|
@@ -56,29 +58,35 @@ void RDSParser::processData(uint16_t block1, uint16_t block2, uint16_t block3, u | |
char c1, c2; | ||
char *p; | ||
|
||
uint16_t mins; ///< RDS time in minutes | ||
uint8_t off; ///< RDS time offset and sign | ||
uint8_t hour; // RDS time in minutes | ||
uint8_t mins; // RDS time in minutes | ||
int8_t off; // RDS time offset and sign | ||
uint32_t MJD; // Modified Julian Day | ||
|
||
// Serial.print('('); Serial.print(block1, HEX); Serial.print(' '); Serial.print(block2, HEX); Serial.print(' '); Serial.print(block3, HEX); Serial.print(' '); Serial.println(block4, HEX); | ||
|
||
if (block1 == 0) { | ||
if (block1 == 0) | ||
{ | ||
// reset all the RDS info. | ||
init(); | ||
// Send out empty data | ||
if (_sendServiceName) _sendServiceName(programServiceName); | ||
if (_sendText) _sendText(""); | ||
if (_sendServiceName) | ||
_sendServiceName(programServiceName); | ||
if (_sendText) | ||
_sendText(""); | ||
return; | ||
} // if | ||
} | ||
|
||
// analyzing Block 2 | ||
rdsGroupType = 0x0A | ((block2 & 0xF000) >> 8) | ((block2 & 0x0800) >> 11); | ||
rdsTP = (block2 & 0x0400); | ||
rdsPTY = (block2 & 0x0400); | ||
|
||
switch (rdsGroupType) { | ||
switch (rdsGroupType) | ||
{ | ||
case 0x0A: | ||
case 0x0B: | ||
// The data received is part of the Service Station Name | ||
// The data received is part of the Service Station Name | ||
idx = 2 * (block2 & 0x0003); | ||
|
||
// new data is 2 chars from block 4 | ||
|
@@ -88,80 +96,94 @@ void RDSParser::processData(uint16_t block1, uint16_t block2, uint16_t block3, u | |
// check that the data was received successfully twice | ||
// before publishing the station name | ||
|
||
if ((_PSName1[idx] == c1) && (_PSName1[idx + 1] == c2)) { | ||
if ((_PSName1[idx] == c1) && (_PSName1[idx + 1] == c2)) | ||
{ | ||
// retrieved the text a second time: store to _PSName2 | ||
_PSName2[idx] = c1; | ||
_PSName2[idx + 1] = c2; | ||
_PSName2[8] = '\0'; | ||
|
||
if ((idx == 6) && strcmp(_PSName1, _PSName2) == 0) { | ||
if (strcmp(_PSName2, programServiceName) != 0) { | ||
if ((idx == 6) && strcmp(_PSName1, _PSName2) == 0) | ||
{ | ||
if (strcmp(_PSName2, programServiceName) != 0) | ||
{ | ||
// publish station name | ||
strcpy(programServiceName, _PSName2); | ||
if (_sendServiceName) | ||
_sendServiceName(programServiceName); | ||
} // if | ||
} // if | ||
} // if | ||
} | ||
} | ||
} | ||
|
||
if ((_PSName1[idx] != c1) || (_PSName1[idx + 1] != c2)) { | ||
if ((_PSName1[idx] != c1) || (_PSName1[idx + 1] != c2)) | ||
{ | ||
_PSName1[idx] = c1; | ||
_PSName1[idx + 1] = c2; | ||
_PSName1[8] = '\0'; | ||
// Serial.println(_PSName1); | ||
} // if | ||
} | ||
break; | ||
|
||
case 0x2A: | ||
// The data received is part of the RDS Text. | ||
_textAB = (block2 & 0x0010); | ||
idx = 4 * (block2 & 0x000F); | ||
|
||
if (idx < _lastTextIDX) { | ||
if (idx < _lastTextIDX) | ||
{ | ||
// the existing text might be complete because the index is starting at the beginning again. | ||
// now send it to the possible listener. | ||
if (_sendText) | ||
// send text if it's different than last sent. | ||
if ((_sendText) && (strncmp(_lastRDSText, _RDSText, sizeof(_RDSText)) != 0)) | ||
{ | ||
memcpy(_lastRDSText, _RDSText, sizeof(_RDSText)); | ||
_sendText(_RDSText); | ||
} | ||
} | ||
_lastTextIDX = idx; | ||
|
||
if (_textAB != _last_textAB) { | ||
if (_textAB != _last_textAB) | ||
{ | ||
// when this bit is toggled the whole buffer should be cleared. | ||
_last_textAB = _textAB; | ||
memset(_RDSText, 0, sizeof(_RDSText)); | ||
// Serial.println("T>CLEAR"); | ||
} // if | ||
|
||
} | ||
|
||
// new data is 2 chars from block 3 | ||
_RDSText[idx] = (block3 >> 8); idx++; | ||
_RDSText[idx] = (block3 & 0x00FF); idx++; | ||
_RDSText[idx] = (block3 >> 8); | ||
idx++; | ||
_RDSText[idx] = (block3 & 0x00FF); | ||
idx++; | ||
|
||
// new data is 2 chars from block 4 | ||
_RDSText[idx] = (block4 >> 8); idx++; | ||
_RDSText[idx] = (block4 & 0x00FF); idx++; | ||
_RDSText[idx] = (block4 >> 8); | ||
idx++; | ||
_RDSText[idx] = (block4 & 0x00FF); | ||
idx++; | ||
|
||
// Serial.print(' '); Serial.println(_RDSText); | ||
// Serial.print("T>"); Serial.println(_RDSText); | ||
break; | ||
|
||
case 0x4A: | ||
// Clock time and date | ||
off = (block4)& 0x3F; // 6 bits | ||
off = (30 * (((block4) & 0x3F) & 0x1F)) / 60; | ||
mins = (block4 >> 6) & 0x3F; // 6 bits | ||
mins += 60 * (((block3 & 0x0001) << 4) | ((block4 >> 12) & 0x0F)); | ||
hour = (((block3 & 0x0001) << 4) | ((block4 >> 12) & 0x0F)); | ||
|
||
MJD = (block3 >> 1); //shift to the right since Bit0 is not relevant | ||
MJD = (MJD | 0x4000) | ((block2 & 0x1) << 14); //Bit 0 of block B becomes bit15 in MJD | ||
MJD = (MJD | 0x8000) | ((block2 & 0x2) << 15); //Bit 1 of block B becomes bit 16 in MJD | ||
|
||
// adjust offset | ||
if (off & 0x20) { | ||
mins -= 30 * (off & 0x1F); | ||
} else { | ||
mins += 30 * (off & 0x1F); | ||
if (((block4) & 0x3F) & 0x20) | ||
{ | ||
off *= -1; | ||
} | ||
|
||
if ((_sendTime) && (mins != _lastRDSMinutes)) { | ||
if ((_sendTime) && (mins != _lastRDSMinutes)) | ||
{ | ||
_lastRDSMinutes = mins; | ||
_sendTime(mins / 60, mins % 60); | ||
} // if | ||
_sendTime(hour, mins, MJD, off); | ||
} | ||
break; | ||
|
||
case 0x6A: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,7 +6,7 @@ | |
/// \copyright Copyright (c) 2014 by Matthias Hertel.\n | ||
/// This work is licensed under a BSD style license.\n | ||
/// See http://www.mathertel.de/License.aspx | ||
/// | ||
/// | ||
/// \details | ||
/// | ||
/// More documentation and source code is available at http://www.mathertel.de/Arduino | ||
|
@@ -16,19 +16,19 @@ | |
/// * 01.09.2014 created and RDS sender name working. | ||
/// * 01.11.2014 RDS time added. | ||
/// * 27.03.2015 Reset RDS data by sending a 0 in blockA in the case the frequency changes. | ||
/// | ||
/// | ||
|
||
|
||
#ifndef __RDSPARSER_H__ | ||
#define __RDSPARSER_H__ | ||
|
||
#include <Arduino.h> | ||
|
||
/// callback function for passing a ServicenName | ||
/// callback function for passing a ServicenName | ||
extern "C" { | ||
typedef void(*receiveServicenNameFunction)(char *name); | ||
typedef void(*receiveTextFunction)(char *name); | ||
typedef void(*receiveTimeFunction)(uint8_t hour, uint8_t minute); | ||
typedef void(*receiveTimeFunction)(uint8_t hour, uint8_t minute, uint32_t MJD, int8_t offset); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pleas add a new callback function to not break compatibility. |
||
} | ||
|
||
|
||
|
@@ -64,7 +64,7 @@ class RDSParser | |
|
||
uint16_t _lastRDSMinutes; ///< last RDS time send to callback. | ||
|
||
char _RDSText[64 + 2]; | ||
char _RDSText[64 + 2], _lastRDSText[64 + 2]; | ||
|
||
}; //RDSParser | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The MDJ structures and functions should be moved into RDSParser to be available is all sketches.