You've already forked TEF6686_ESP32
internal changes, remove useless things
This commit is contained in:
@@ -8,6 +8,10 @@ The version in the repository is an ongoing development. It could and will conta
|
||||
Advanced Tuner software for NXP TEF668x tuners with ESP32 board
|
||||
More information: https://www.pe5pvb.nl/tef6686/
|
||||
|
||||
## Time
|
||||
|
||||
You can receive CT time over the RDS on FM, DP666 receivers have a RX8010SJ (driver written by [Wh1teRabbitHU](https://github.com/Wh1teRabbitHU)) and thus can save time between boots, making the radio a high accuracy clock. Enabling the RDS Filter option can delay the clock by a few seconds, however without the filter the clock (from RDS CT) is in perfect sync with my Windows computer synced by NTP
|
||||
|
||||
## Wiki
|
||||
- [About the software & features](https://github.com/PE5PVB/TEF6686_ESP32/wiki)
|
||||
- [Getting started](https://github.com/PE5PVB/TEF6686_ESP32/wiki#getting-started)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#pragma once
|
||||
#include <TimeLib.h>
|
||||
#include "globals.h"
|
||||
#include "rtc.hpp"
|
||||
|
||||
|
||||
@@ -79,8 +79,7 @@ bool devTEF_Get_Cmd(TEF_MODULE module, uint8_t cmd, uint8_t *receive, uint16_t l
|
||||
void devTEF_Radio_Set_Wavegen(bool mode, int16_t amplitude, uint16_t freq);
|
||||
|
||||
void devTEF_Radio_Get_Quality_Status(uint16_t *status, int16_t *level, uint16_t *usn, uint16_t *wam, int16_t *offset, uint16_t *bandwidth, uint16_t *mod, int8_t *snr);
|
||||
bool devTEF_Radio_Get_Processing_Status(uint16_t *highcut, uint16_t *stereo, uint16_t *sthiblend, uint8_t *stband_1, uint8_t *stband_2, uint8_t *stband_3, uint8_t *stband_4);
|
||||
uint8_t devTEF_APPL_Get_Operation_Status();
|
||||
bool devTEF_Radio_Get_Stereo_Status(uint16_t *status);
|
||||
void devTEF_Radio_Get_RDS_Status(uint16_t *status, uint16_t *A_block, uint16_t *B_block, uint16_t *C_block, uint16_t *D_block, uint16_t *dec_error);
|
||||
bool devTEF_Radio_Get_RDS_Data(uint16_t *status, uint16_t *A_block, uint16_t *B_block, uint16_t *C_block, uint16_t *D_block, uint16_t *dec_error);
|
||||
void devTEF_Radio_Get_RDS_Data(uint16_t *status, uint16_t *A_block, uint16_t *B_block, uint16_t *C_block, uint16_t *D_block, uint16_t *dec_error);
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#define VERSION "v2.20.5d"
|
||||
#define VERSION "v2.20.5e"
|
||||
|
||||
#define ROTARY_PIN_A 34
|
||||
#define ROTARY_PIN_B 36
|
||||
@@ -48,10 +48,7 @@
|
||||
#define BATTERY_LOW_VALUE 3.2
|
||||
#define BATTERY_FULL_VALUE 4.12
|
||||
|
||||
#define XTAL_0V_ADC 0
|
||||
#define XTAL_1V_ADC 1050
|
||||
#define XTAL_2V_ADC 2250
|
||||
#define XTAL_ADC_TOL 300
|
||||
#define XTAL_MV_TOL 300
|
||||
|
||||
#define LANGUAGE_CHS 14
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <ctime>
|
||||
#include "constants.h"
|
||||
#include <ESP32Time.h>
|
||||
#include <RX8010SJ.h>
|
||||
@@ -11,8 +12,5 @@ extern ESP32Time rtc;
|
||||
extern bool rx_rtc_avail;
|
||||
extern RX8010SJ::Adapter rx_rtc;
|
||||
|
||||
void timeToDateTime(time_t t, struct RX8010SJ::DateTime* dateTime);
|
||||
time_t dateTimeToTime(const struct RX8010SJ::DateTime* dateTime);
|
||||
|
||||
void sync_to_rx_rtc(int32_t offset = 0);
|
||||
void sync_from_rx_rtc(int32_t offset = 0);
|
||||
void sync_from_rx_rtc(int32_t offset = 0);
|
||||
void set_time(time_t time);
|
||||
@@ -1411,31 +1411,16 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *da
|
||||
end_tft_write();
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: setSwapBytes
|
||||
** Description: Used by 16-bit pushImage() to swap byte order in colours
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::setSwapBytes(bool swap)
|
||||
{
|
||||
_swapBytes = swap;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: getSwapBytes
|
||||
** Description: Return the swap byte order for colours
|
||||
***************************************************************************************/
|
||||
bool TFT_eSPI::getSwapBytes(void)
|
||||
{
|
||||
return _swapBytes;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: read rectangle (for SPI Interface II i.e. IM [3:0] = "1101")
|
||||
** Description: Read RGB pixel colours from a defined area
|
||||
***************************************************************************************/
|
||||
// If w and h are 1, then 1 pixel is read, *data array size must be 3 bytes per pixel
|
||||
void TFT_eSPI::readRectRGB(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_t *data) {
|
||||
begin_tft_read();
|
||||
|
||||
@@ -1893,11 +1878,6 @@ void TFT_eSPI::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w
|
||||
end_tft_write(); // Does nothing if Sprite class uses this function
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: drawBitmap
|
||||
** Description: Draw an image stored in an array on the TFT
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor, uint16_t bgcolor)
|
||||
{
|
||||
//begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
|
||||
@@ -1917,10 +1897,6 @@ void TFT_eSPI::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w
|
||||
end_tft_write(); // Does nothing if Sprite class uses this function
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: drawXBitmap
|
||||
** Description: Draw an image stored in an XBM array onto the TFT
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color)
|
||||
{
|
||||
//begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
|
||||
@@ -1941,10 +1917,6 @@ void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: drawXBitmap
|
||||
** Description: Draw an XBM image with foreground and background colors
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bgcolor)
|
||||
{
|
||||
//begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
|
||||
@@ -1964,22 +1936,12 @@ void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t
|
||||
end_tft_write(); // Does nothing if Sprite class uses this function
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: setCursor
|
||||
** Description: Set the text cursor x,y position
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::setCursor(int16_t x, int16_t y)
|
||||
{
|
||||
cursor_x = x;
|
||||
cursor_y = y;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: setCursor
|
||||
** Description: Set the text cursor x,y position and font
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::setCursor(int16_t x, int16_t y, uint8_t font)
|
||||
{
|
||||
setTextFont(font);
|
||||
@@ -1987,21 +1949,12 @@ void TFT_eSPI::setCursor(int16_t x, int16_t y, uint8_t font)
|
||||
cursor_y = y;
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: setTextSize
|
||||
** Description: Set the text size multiplier
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::setTextSize(uint8_t s)
|
||||
{
|
||||
if (s>7) s = 7; // Limit the maximum size multiplier so byte variables can be used for rendering
|
||||
textsize = (s > 0) ? s : 1; // Don't allow font size 0
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: setTextColor
|
||||
** Description: Set the font foreground colour (background is transparent)
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::setTextColor(uint16_t c)
|
||||
{
|
||||
// For 'transparent' background, we'll set the bg
|
||||
@@ -2009,14 +1962,6 @@ void TFT_eSPI::setTextColor(uint16_t c)
|
||||
textcolor = textbgcolor = c;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: setTextColor
|
||||
** Description: Set the font foreground and background colour
|
||||
***************************************************************************************/
|
||||
// Smooth fonts use the background colour for anti-aliasing and by default the
|
||||
// background is not filled. If bgfill = true, then a smooth font background fill will
|
||||
// be used.
|
||||
void TFT_eSPI::setTextColor(uint16_t c, uint16_t b, bool bgfill)
|
||||
{
|
||||
textcolor = c;
|
||||
@@ -2024,21 +1969,12 @@ void TFT_eSPI::setTextColor(uint16_t c, uint16_t b, bool bgfill)
|
||||
_fillbg = bgfill;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: setPivot
|
||||
** Description: Set the pivot point on the TFT
|
||||
*************************************************************************************x*/
|
||||
void TFT_eSPI::setPivot(int16_t x, int16_t y)
|
||||
{
|
||||
_xPivot = x;
|
||||
_yPivot = y;
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: setBitmapColor
|
||||
** Description: Set the foreground foreground and background colour
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::setBitmapColor(uint16_t c, uint16_t b)
|
||||
{
|
||||
if (c == b) b = ~c;
|
||||
@@ -2046,32 +1982,17 @@ void TFT_eSPI::setBitmapColor(uint16_t c, uint16_t b)
|
||||
bitmap_bg = b;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: setTextWrap
|
||||
** Description: Define if text should wrap at end of line
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::setTextWrap(bool wrapX, bool wrapY)
|
||||
{
|
||||
textwrapX = wrapX;
|
||||
textwrapY = wrapY;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: setTextDatum
|
||||
** Description: Set the text position reference datum
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::setTextDatum(uint8_t d)
|
||||
{
|
||||
textdatum = d;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: setTextPadding
|
||||
** Description: Define padding width (aids erasing old text and numbers)
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::setTextPadding(uint16_t x_width)
|
||||
{
|
||||
padX = x_width;
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
/* DateStrings.cpp
|
||||
* Definitions for date strings for use with the Time library
|
||||
*
|
||||
* Updated for Arduino 1.5.7 18 July 2014
|
||||
*
|
||||
* No memory is consumed in the sketch if your code does not call any of the string methods
|
||||
* You can change the text of the strings, make sure the short strings are each exactly 3 characters
|
||||
* the long strings can be any length up to the constant dt_MAX_STRING_LEN defined in TimeLib.h
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
// Arduino.h should properly define PROGMEM, PGM_P, strcpy_P, pgm_read_byte, pgm_read_ptr
|
||||
// But not all platforms define these as they should. If you find a platform needing these
|
||||
// defined, or if any this becomes unnecessary as platforms improve, please send a pull req.
|
||||
#if defined(ESP8266)
|
||||
#undef PROGMEM
|
||||
#define PROGMEM
|
||||
#endif
|
||||
|
||||
#include "TimeLib.h"
|
||||
|
||||
|
||||
// the short strings for each day or month must be exactly dt_SHORT_STR_LEN
|
||||
#define dt_SHORT_STR_LEN 3 // the length of short strings
|
||||
|
||||
static char buffer[dt_MAX_STRING_LEN+1]; // must be big enough for longest string and the terminating null
|
||||
|
||||
const char monthStr0[] PROGMEM = "";
|
||||
const char monthStr1[] PROGMEM = "January";
|
||||
const char monthStr2[] PROGMEM = "February";
|
||||
const char monthStr3[] PROGMEM = "March";
|
||||
const char monthStr4[] PROGMEM = "April";
|
||||
const char monthStr5[] PROGMEM = "May";
|
||||
const char monthStr6[] PROGMEM = "June";
|
||||
const char monthStr7[] PROGMEM = "July";
|
||||
const char monthStr8[] PROGMEM = "August";
|
||||
const char monthStr9[] PROGMEM = "September";
|
||||
const char monthStr10[] PROGMEM = "October";
|
||||
const char monthStr11[] PROGMEM = "November";
|
||||
const char monthStr12[] PROGMEM = "December";
|
||||
|
||||
const PROGMEM char * const PROGMEM monthNames_P[] =
|
||||
{
|
||||
monthStr0,monthStr1,monthStr2,monthStr3,monthStr4,monthStr5,monthStr6,
|
||||
monthStr7,monthStr8,monthStr9,monthStr10,monthStr11,monthStr12
|
||||
};
|
||||
|
||||
const char monthShortNames_P[] PROGMEM = "ErrJanFebMarAprMayJunJulAugSepOctNovDec";
|
||||
|
||||
const char dayStr0[] PROGMEM = "Err";
|
||||
const char dayStr1[] PROGMEM = "Sunday";
|
||||
const char dayStr2[] PROGMEM = "Monday";
|
||||
const char dayStr3[] PROGMEM = "Tuesday";
|
||||
const char dayStr4[] PROGMEM = "Wednesday";
|
||||
const char dayStr5[] PROGMEM = "Thursday";
|
||||
const char dayStr6[] PROGMEM = "Friday";
|
||||
const char dayStr7[] PROGMEM = "Saturday";
|
||||
|
||||
const PROGMEM char * const PROGMEM dayNames_P[] =
|
||||
{
|
||||
dayStr0,dayStr1,dayStr2,dayStr3,dayStr4,dayStr5,dayStr6,dayStr7
|
||||
};
|
||||
|
||||
const char dayShortNames_P[] PROGMEM = "ErrSunMonTueWedThuFriSat";
|
||||
|
||||
/* functions to return date strings */
|
||||
|
||||
char* monthStr(uint8_t month)
|
||||
{
|
||||
strcpy_P(buffer, (PGM_P)pgm_read_ptr(&(monthNames_P[month])));
|
||||
return buffer;
|
||||
}
|
||||
|
||||
char* monthShortStr(uint8_t month)
|
||||
{
|
||||
for (int i=0; i < dt_SHORT_STR_LEN; i++)
|
||||
buffer[i] = pgm_read_byte(&(monthShortNames_P[i+ (month*dt_SHORT_STR_LEN)]));
|
||||
buffer[dt_SHORT_STR_LEN] = 0;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
char* dayStr(uint8_t day)
|
||||
{
|
||||
strcpy_P(buffer, (PGM_P)pgm_read_ptr(&(dayNames_P[day])));
|
||||
return buffer;
|
||||
}
|
||||
|
||||
char* dayShortStr(uint8_t day)
|
||||
{
|
||||
uint8_t index = day*dt_SHORT_STR_LEN;
|
||||
for (int i=0; i < dt_SHORT_STR_LEN; i++)
|
||||
buffer[i] = pgm_read_byte(&(dayShortNames_P[index + i]));
|
||||
buffer[dt_SHORT_STR_LEN] = 0;
|
||||
return buffer;
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
# Arduino Time Library
|
||||
|
||||
Time is a library that provides timekeeping functionality for Arduino.
|
||||
|
||||
Using the Arduino Library Manager, install "*Time* by *Michael Margolis*".
|
||||
|
||||
The code is derived from the Playground DateTime library but is updated
|
||||
to provide an API that is more flexible and easier to use.
|
||||
|
||||
A primary goal was to enable date and time functionality that can be used with
|
||||
a variety of external time sources with minimum differences required in sketch logic.
|
||||
|
||||
Example sketches illustrate how similar sketch code can be used with: a Real Time Clock,
|
||||
internet NTP time service, GPS time data, and Serial time messages from a computer
|
||||
for time synchronization.
|
||||
|
||||
## Functionality
|
||||
|
||||
To use the Time library in an Arduino sketch, include TimeLib.h.
|
||||
|
||||
```c
|
||||
#include <TimeLib.h>
|
||||
```
|
||||
|
||||
The functions available in the library include
|
||||
|
||||
```c
|
||||
hour(); // the hour now (0-23)
|
||||
minute(); // the minute now (0-59)
|
||||
second(); // the second now (0-59)
|
||||
day(); // the day now (1-31)
|
||||
weekday(); // day of the week (1-7), Sunday is day 1
|
||||
month(); // the month now (1-12)
|
||||
year(); // the full four digit year: (2009, 2010 etc)
|
||||
```
|
||||
|
||||
there are also functions to return the hour in 12-hour format
|
||||
|
||||
```c
|
||||
hourFormat12(); // the hour now in 12 hour format
|
||||
isAM(); // returns true if time now is AM
|
||||
isPM(); // returns true if time now is PM
|
||||
|
||||
now(); // returns the current time as seconds since Jan 1 1970
|
||||
```
|
||||
|
||||
The time and date functions can take an optional parameter for the time. This prevents
|
||||
errors if the time rolls over between elements. For example, if a new minute begins
|
||||
between getting the minute and second, the values will be inconsistent. Using the
|
||||
following functions eliminates this problem
|
||||
|
||||
```c
|
||||
time_t t = now(); // store the current time in time variable t
|
||||
hour(t); // returns the hour for the given time t
|
||||
minute(t); // returns the minute for the given time t
|
||||
second(t); // returns the second for the given time t
|
||||
day(t); // the day for the given time t
|
||||
weekday(t); // day of the week for the given time t
|
||||
month(t); // the month for the given time t
|
||||
year(t); // the year for the given time t
|
||||
```
|
||||
|
||||
Functions for managing the timer services are:
|
||||
|
||||
```c
|
||||
setTime(t); // set the system time to the give time t
|
||||
setTime(hr,min,sec,day,mnth,yr); // alternative to above, yr is 2 or 4 digit yr
|
||||
// (2010 or 10 sets year to 2010)
|
||||
adjustTime(adjustment); // adjust system time by adding the adjustment value
|
||||
timeStatus(); // indicates if time has been set and recently synchronized
|
||||
// returns one of the following enumerations:
|
||||
timeNotSet // the time has never been set, the clock started on Jan 1, 1970
|
||||
timeNeedsSync // the time had been set but a sync attempt did not succeed
|
||||
timeSet // the time is set and is synced
|
||||
```
|
||||
|
||||
Time and Date values are not valid if the status is `timeNotSet`. Otherwise, values can be used but
|
||||
the returned time may have drifted if the status is `timeNeedsSync`.
|
||||
|
||||
```c
|
||||
setSyncProvider(getTimeFunction); // set the external time provider
|
||||
setSyncInterval(interval); // set the number of seconds between re-sync
|
||||
```
|
||||
|
||||
There are many convenience macros in the `time.h` file for time constants and conversion
|
||||
of time units.
|
||||
|
||||
To use the library, copy the download to the Library directory.
|
||||
|
||||
## Examples
|
||||
|
||||
The Time directory contains the Time library and some example sketches
|
||||
illustrating how the library can be used with various time sources:
|
||||
|
||||
- `TimeSerial.pde` shows Arduino as a clock without external hardware.
|
||||
It is synchronized by time messages sent over the serial port.
|
||||
A companion Processing sketch will automatically provide these messages
|
||||
if it is running and connected to the Arduino serial port.
|
||||
|
||||
- `TimeSerialDateStrings.pde` adds day and month name strings to the sketch above.
|
||||
Short (3 characters) and long strings are available to print the days of
|
||||
the week and names of the months.
|
||||
|
||||
- `TimeRTC` uses a DS1307 real-time clock to provide time synchronization.
|
||||
The basic [DS1307RTC library][1] must be downloaded and installed,
|
||||
in order to run this sketch.
|
||||
|
||||
- `TimeRTCSet` is similar to the above and adds the ability to set the Real Time Clock.
|
||||
|
||||
- `TimeRTCLog` demonstrates how to calculate the difference between times.
|
||||
It is a very simple logger application that monitors events on digital pins
|
||||
and prints (to the serial port) the time of an event and the time period since
|
||||
the previous event.
|
||||
|
||||
- `TimeNTP` uses the Arduino Ethernet shield to access time using the internet NTP time service.
|
||||
The NTP protocol uses UDP and the UdpBytewise library is required, see:
|
||||
<http://bitbucket.org/bjoern/arduino_osc/src/14667490521f/libraries/Ethernet/>
|
||||
|
||||
- `TimeGPS` gets time from a GPS.
|
||||
This requires the TinyGPS library from Mikal Hart:
|
||||
<http://arduiniana.org/libraries/TinyGPS>
|
||||
|
||||
## Differences
|
||||
|
||||
Differences between this code and the playground DateTime library
|
||||
although the Time library is based on the DateTime codebase, the API has changed.
|
||||
Changes in the Time library API:
|
||||
|
||||
- time elements are functions returning `int` (they are variables in DateTime)
|
||||
- Years start from 1970
|
||||
- days of the week and months start from 1 (they start from 0 in DateTime)
|
||||
- DateStrings do not require a separate library
|
||||
- time elements can be accessed non-atomically (in DateTime they are always atomic)
|
||||
- function added to automatically sync time with external source
|
||||
- `localTime` and `maketime` parameters changed, `localTime` renamed to `breakTime`
|
||||
|
||||
## Technical Notes
|
||||
|
||||
Internal system time is based on the standard Unix `time_t`.
|
||||
The value is the number of seconds since Jan 1, 1970.
|
||||
System time begins at zero when the sketch starts.
|
||||
|
||||
The internal time can be automatically synchronized at regular intervals to an external time source.
|
||||
This is enabled by calling the `setSyncProvider(provider)` function - the provider argument is
|
||||
the address of a function that returns the current time as a `time_t`.
|
||||
See the sketches in the examples directory for usage.
|
||||
|
||||
The default interval for re-syncing the time is 5 minutes but can be changed by calling the
|
||||
`setSyncInterval(interval)` method to set the number of seconds between re-sync attempts.
|
||||
|
||||
The Time library defines a structure for holding time elements that is a compact version of the C `tm` structure.
|
||||
All the members of the Arduino `tm` structure are bytes and the year is offset from 1970.
|
||||
Convenience macros provide conversion to and from the Arduino format.
|
||||
|
||||
Low-level functions to convert between system time and individual time elements are provided:
|
||||
|
||||
```c
|
||||
breakTime(time, &tm); // break time_t into elements stored in tm struct
|
||||
makeTime(&tm); // return time_t from elements stored in tm struct
|
||||
```
|
||||
|
||||
This [DS1307RTC library][1] provides an example of how a time provider
|
||||
can use the low-level functions to interface with the Time library.
|
||||
|
||||
[1]:<https://github.com/PaulStoffregen/DS1307RTC>
|
||||
@@ -1,321 +0,0 @@
|
||||
/*
|
||||
time.c - low level time and date functions
|
||||
Copyright (c) Michael Margolis 2009-2014
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
1.0 6 Jan 2010 - initial release
|
||||
1.1 12 Feb 2010 - fixed leap year calculation error
|
||||
1.2 1 Nov 2010 - fixed setTime bug (thanks to Korman for this)
|
||||
1.3 24 Mar 2012 - many edits by Paul Stoffregen: fixed timeStatus() to update
|
||||
status, updated examples for Arduino 1.0, fixed ARM
|
||||
compatibility issues, added TimeArduinoDue and TimeTeensy3
|
||||
examples, add error checking and messages to RTC examples,
|
||||
add examples to DS1307RTC library.
|
||||
1.4 5 Sep 2014 - compatibility with Arduino 1.5.7
|
||||
*/
|
||||
|
||||
#if ARDUINO >= 100
|
||||
#include <Arduino.h>
|
||||
#else
|
||||
#include <WProgram.h>
|
||||
#endif
|
||||
|
||||
#include "TimeLib.h"
|
||||
|
||||
static tmElements_t tm; // a cache of time elements
|
||||
static time_t cacheTime; // the time the cache was updated
|
||||
static uint32_t syncInterval = 300; // time sync will be attempted after this many seconds
|
||||
|
||||
void refreshCache(time_t t) {
|
||||
if (t != cacheTime) {
|
||||
breakTime(t, tm);
|
||||
cacheTime = t;
|
||||
}
|
||||
}
|
||||
|
||||
int hour() { // the hour now
|
||||
return hour(now());
|
||||
}
|
||||
|
||||
int hour(time_t t) { // the hour for the given time
|
||||
refreshCache(t);
|
||||
return tm.Hour;
|
||||
}
|
||||
|
||||
int hourFormat12() { // the hour now in 12 hour format
|
||||
return hourFormat12(now());
|
||||
}
|
||||
|
||||
int hourFormat12(time_t t) { // the hour for the given time in 12 hour format
|
||||
refreshCache(t);
|
||||
if( tm.Hour == 0 )
|
||||
return 12; // 12 midnight
|
||||
else if( tm.Hour > 12)
|
||||
return tm.Hour - 12 ;
|
||||
else
|
||||
return tm.Hour ;
|
||||
}
|
||||
|
||||
uint8_t isAM() { // returns true if time now is AM
|
||||
return !isPM(now());
|
||||
}
|
||||
|
||||
uint8_t isAM(time_t t) { // returns true if given time is AM
|
||||
return !isPM(t);
|
||||
}
|
||||
|
||||
uint8_t isPM() { // returns true if PM
|
||||
return isPM(now());
|
||||
}
|
||||
|
||||
uint8_t isPM(time_t t) { // returns true if PM
|
||||
return (hour(t) >= 12);
|
||||
}
|
||||
|
||||
int minute() {
|
||||
return minute(now());
|
||||
}
|
||||
|
||||
int minute(time_t t) { // the minute for the given time
|
||||
refreshCache(t);
|
||||
return tm.Minute;
|
||||
}
|
||||
|
||||
int second() {
|
||||
return second(now());
|
||||
}
|
||||
|
||||
int second(time_t t) { // the second for the given time
|
||||
refreshCache(t);
|
||||
return tm.Second;
|
||||
}
|
||||
|
||||
int day(){
|
||||
return(day(now()));
|
||||
}
|
||||
|
||||
int day(time_t t) { // the day for the given time (0-6)
|
||||
refreshCache(t);
|
||||
return tm.Day;
|
||||
}
|
||||
|
||||
int weekday() { // Sunday is day 1
|
||||
return weekday(now());
|
||||
}
|
||||
|
||||
int weekday(time_t t) {
|
||||
refreshCache(t);
|
||||
return tm.Wday;
|
||||
}
|
||||
|
||||
int month(){
|
||||
return month(now());
|
||||
}
|
||||
|
||||
int month(time_t t) { // the month for the given time
|
||||
refreshCache(t);
|
||||
return tm.Month;
|
||||
}
|
||||
|
||||
int year() { // as in Processing, the full four digit year: (2009, 2010 etc)
|
||||
return year(now());
|
||||
}
|
||||
|
||||
int year(time_t t) { // the year for the given time
|
||||
refreshCache(t);
|
||||
return tmYearToCalendar(tm.Year);
|
||||
}
|
||||
|
||||
/*============================================================================*/
|
||||
/* functions to convert to and from system time */
|
||||
/* These are for interfacing with time services and are not normally needed in a sketch */
|
||||
|
||||
// leap year calculator expects year argument as years offset from 1970
|
||||
#define LEAP_YEAR(Y) ( ((1970+(Y))>0) && !((1970+(Y))%4) && ( ((1970+(Y))%100) || !((1970+(Y))%400) ) )
|
||||
|
||||
static const uint8_t monthDays[]={31,28,31,30,31,30,31,31,30,31,30,31}; // API starts months from 1, this array starts from 0
|
||||
|
||||
void breakTime(time_t timeInput, tmElements_t &tm){
|
||||
// break the given time_t into time components
|
||||
// this is a more compact version of the C library localtime function
|
||||
// note that year is offset from 1970 !!!
|
||||
|
||||
uint8_t year;
|
||||
uint8_t month, monthLength;
|
||||
uint32_t time;
|
||||
unsigned long days;
|
||||
|
||||
time = (uint32_t)timeInput;
|
||||
tm.Second = time % 60;
|
||||
time /= 60; // now it is minutes
|
||||
tm.Minute = time % 60;
|
||||
time /= 60; // now it is hours
|
||||
tm.Hour = time % 24;
|
||||
time /= 24; // now it is days
|
||||
tm.Wday = ((time + 4) % 7) + 1; // Sunday is day 1
|
||||
|
||||
year = 0;
|
||||
days = 0;
|
||||
while((unsigned)(days += (LEAP_YEAR(year) ? 366 : 365)) <= time) {
|
||||
year++;
|
||||
}
|
||||
tm.Year = year; // year is offset from 1970
|
||||
|
||||
days -= LEAP_YEAR(year) ? 366 : 365;
|
||||
time -= days; // now it is days in this year, starting at 0
|
||||
|
||||
days=0;
|
||||
month=0;
|
||||
monthLength=0;
|
||||
for (month=0; month<12; month++) {
|
||||
if (month==1) { // february
|
||||
if (LEAP_YEAR(year)) {
|
||||
monthLength=29;
|
||||
} else {
|
||||
monthLength=28;
|
||||
}
|
||||
} else {
|
||||
monthLength = monthDays[month];
|
||||
}
|
||||
|
||||
if (time >= monthLength) {
|
||||
time -= monthLength;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
tm.Month = month + 1; // jan is month 1
|
||||
tm.Day = time + 1; // day of month
|
||||
}
|
||||
|
||||
time_t makeTime(const tmElements_t &tm){
|
||||
// assemble time elements into time_t
|
||||
// note year argument is offset from 1970 (see macros in time.h to convert to other formats)
|
||||
// previous version used full four digit year (or digits since 2000),i.e. 2009 was 2009 or 9
|
||||
|
||||
int i;
|
||||
uint32_t seconds;
|
||||
|
||||
// seconds from 1970 till 1 jan 00:00:00 of the given year
|
||||
seconds= tm.Year*(SECS_PER_DAY * 365);
|
||||
for (i = 0; i < tm.Year; i++) {
|
||||
if (LEAP_YEAR(i)) {
|
||||
seconds += SECS_PER_DAY; // add extra days for leap years
|
||||
}
|
||||
}
|
||||
|
||||
// add days for this year, months start from 1
|
||||
for (i = 1; i < tm.Month; i++) {
|
||||
if ( (i == 2) && LEAP_YEAR(tm.Year)) {
|
||||
seconds += SECS_PER_DAY * 29;
|
||||
} else {
|
||||
seconds += SECS_PER_DAY * monthDays[i-1]; //monthDay array starts from 0
|
||||
}
|
||||
}
|
||||
seconds+= (tm.Day-1) * SECS_PER_DAY;
|
||||
seconds+= tm.Hour * SECS_PER_HOUR;
|
||||
seconds+= tm.Minute * SECS_PER_MIN;
|
||||
seconds+= tm.Second;
|
||||
return (time_t)seconds;
|
||||
}
|
||||
/*=====================================================*/
|
||||
/* Low level system time functions */
|
||||
|
||||
static uint32_t sysTime = 0;
|
||||
static uint32_t prevMillis = 0;
|
||||
static uint32_t nextSyncTime = 0;
|
||||
static timeStatus_t Status = timeNotSet;
|
||||
|
||||
getExternalTime getTimePtr; // pointer to external sync function
|
||||
//setExternalTime setTimePtr; // not used in this version
|
||||
|
||||
#ifdef TIME_DRIFT_INFO // define this to get drift data
|
||||
time_t sysUnsyncedTime = 0; // the time sysTime unadjusted by sync
|
||||
#endif
|
||||
|
||||
|
||||
time_t now() {
|
||||
// calculate number of seconds passed since last call to now()
|
||||
while (millis() - prevMillis >= 1000) {
|
||||
// millis() and prevMillis are both unsigned ints thus the subtraction will always be the absolute value of the difference
|
||||
sysTime++;
|
||||
prevMillis += 1000;
|
||||
#ifdef TIME_DRIFT_INFO
|
||||
sysUnsyncedTime++; // this can be compared to the synced time to measure long term drift
|
||||
#endif
|
||||
}
|
||||
if (nextSyncTime <= sysTime) {
|
||||
if (getTimePtr != 0) {
|
||||
time_t t = getTimePtr();
|
||||
if (t != 0) {
|
||||
setTime(t);
|
||||
} else {
|
||||
nextSyncTime = sysTime + syncInterval;
|
||||
Status = (Status == timeNotSet) ? timeNotSet : timeNeedsSync;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (time_t)sysTime;
|
||||
}
|
||||
|
||||
void setTime(time_t t) {
|
||||
#ifdef TIME_DRIFT_INFO
|
||||
if(sysUnsyncedTime == 0)
|
||||
sysUnsyncedTime = t; // store the time of the first call to set a valid Time
|
||||
#endif
|
||||
|
||||
sysTime = (uint32_t)t;
|
||||
nextSyncTime = (uint32_t)t + syncInterval;
|
||||
Status = timeSet;
|
||||
prevMillis = millis(); // restart counting from now (thanks to Korman for this fix)
|
||||
}
|
||||
|
||||
void setTime(int hr,int min,int sec,int dy, int mnth, int yr){
|
||||
// year can be given as full four digit year or two digts (2010 or 10 for 2010);
|
||||
//it is converted to years since 1970
|
||||
if( yr > 99)
|
||||
yr = yr - 1970;
|
||||
else
|
||||
yr += 30;
|
||||
tm.Year = yr;
|
||||
tm.Month = mnth;
|
||||
tm.Day = dy;
|
||||
tm.Hour = hr;
|
||||
tm.Minute = min;
|
||||
tm.Second = sec;
|
||||
setTime(makeTime(tm));
|
||||
}
|
||||
|
||||
void adjustTime(long adjustment) {
|
||||
sysTime += adjustment;
|
||||
}
|
||||
|
||||
// indicates if time has been set and recently synchronized
|
||||
timeStatus_t timeStatus() {
|
||||
now(); // required to actually update the status
|
||||
return Status;
|
||||
}
|
||||
|
||||
void setSyncProvider( getExternalTime getTimeFunction){
|
||||
getTimePtr = getTimeFunction;
|
||||
nextSyncTime = sysTime;
|
||||
now(); // this will sync the clock
|
||||
}
|
||||
|
||||
void setSyncInterval(time_t interval){ // set the number of seconds between re-sync
|
||||
syncInterval = (uint32_t)interval;
|
||||
nextSyncTime = sysTime + syncInterval;
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
/*
|
||||
time.h - low level time and date functions
|
||||
*/
|
||||
|
||||
/*
|
||||
July 3 2011 - fixed elapsedSecsThisWeek macro (thanks Vincent Valdy for this)
|
||||
- fixed daysToTime_t macro (thanks maniacbug)
|
||||
*/
|
||||
|
||||
#ifndef _Time_h
|
||||
#ifdef __cplusplus
|
||||
#define _Time_h
|
||||
|
||||
#include <inttypes.h>
|
||||
#ifndef __AVR__
|
||||
#include <sys/types.h> // for __time_t_defined, but avr libc lacks sys/types.h
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(__time_t_defined) // avoid conflict with newlib or other posix libc
|
||||
typedef unsigned long time_t;
|
||||
#endif
|
||||
|
||||
|
||||
// This ugly hack allows us to define C++ overloaded functions, when included
|
||||
// from within an extern "C", as newlib's sys/stat.h does. Actually it is
|
||||
// intended to include "time.h" from the C library (on ARM, but AVR does not
|
||||
// have that file at all). On Mac and Windows, the compiler will find this
|
||||
// "Time.h" instead of the C library "time.h", so we may cause other weird
|
||||
// and unpredictable effects by conflicting with the C library header "time.h",
|
||||
// but at least this hack lets us define C++ functions as intended. Hopefully
|
||||
// nothing too terrible will result from overriding the C library header?!
|
||||
extern "C++" {
|
||||
typedef enum {timeNotSet, timeNeedsSync, timeSet
|
||||
} timeStatus_t ;
|
||||
|
||||
typedef enum {
|
||||
dowInvalid, dowSunday, dowMonday, dowTuesday, dowWednesday, dowThursday, dowFriday, dowSaturday
|
||||
} timeDayOfWeek_t;
|
||||
|
||||
typedef enum {
|
||||
tmSecond, tmMinute, tmHour, tmWday, tmDay,tmMonth, tmYear, tmNbrFields
|
||||
} tmByteFields;
|
||||
|
||||
typedef struct {
|
||||
uint8_t Second;
|
||||
uint8_t Minute;
|
||||
uint8_t Hour;
|
||||
uint8_t Wday; // day of week, sunday is day 1
|
||||
uint8_t Day;
|
||||
uint8_t Month;
|
||||
uint8_t Year; // offset from 1970;
|
||||
} tmElements_t, TimeElements, *tmElementsPtr_t;
|
||||
|
||||
//convenience macros to convert to and from tm years
|
||||
#define tmYearToCalendar(Y) ((Y) + 1970) // full four digit year
|
||||
#define CalendarYrToTm(Y) ((Y) - 1970)
|
||||
#define tmYearToY2k(Y) ((Y) - 30) // offset is from 2000
|
||||
#define y2kYearToTm(Y) ((Y) + 30)
|
||||
|
||||
typedef time_t(*getExternalTime)();
|
||||
//typedef void (*setExternalTime)(const time_t); // not used in this version
|
||||
|
||||
|
||||
/*==============================================================================*/
|
||||
/* Useful Constants */
|
||||
#define SECS_PER_MIN ((time_t)(60UL))
|
||||
#define SECS_PER_HOUR ((time_t)(3600UL))
|
||||
#define SECS_PER_DAY ((time_t)(SECS_PER_HOUR * 24UL))
|
||||
#define DAYS_PER_WEEK ((time_t)(7UL))
|
||||
#define SECS_PER_WEEK ((time_t)(SECS_PER_DAY * DAYS_PER_WEEK))
|
||||
#define SECS_PER_YEAR ((time_t)(SECS_PER_DAY * 365UL)) // TODO: ought to handle leap years
|
||||
#define SECS_YR_2000 ((time_t)(946684800UL)) // the time at the start of y2k
|
||||
|
||||
/* Useful Macros for getting elapsed time */
|
||||
#define numberOfSeconds(_time_) ((_time_) % SECS_PER_MIN)
|
||||
#define numberOfMinutes(_time_) (((_time_) / SECS_PER_MIN) % SECS_PER_MIN)
|
||||
#define numberOfHours(_time_) (((_time_) % SECS_PER_DAY) / SECS_PER_HOUR)
|
||||
#define dayOfWeek(_time_) ((((_time_) / SECS_PER_DAY + 4) % DAYS_PER_WEEK)+1) // 1 = Sunday
|
||||
#define elapsedDays(_time_) ((_time_) / SECS_PER_DAY) // this is number of days since Jan 1 1970
|
||||
#define elapsedSecsToday(_time_) ((_time_) % SECS_PER_DAY) // the number of seconds since last midnight
|
||||
// The following macros are used in calculating alarms and assume the clock is set to a date later than Jan 1 1971
|
||||
// Always set the correct time before setting alarms
|
||||
#define previousMidnight(_time_) (((_time_) / SECS_PER_DAY) * SECS_PER_DAY) // time at the start of the given day
|
||||
#define nextMidnight(_time_) (previousMidnight(_time_) + SECS_PER_DAY) // time at the end of the given day
|
||||
#define elapsedSecsThisWeek(_time_) (elapsedSecsToday(_time_) + ((dayOfWeek(_time_)-1) * SECS_PER_DAY)) // note that week starts on day 1
|
||||
#define previousSunday(_time_) ((_time_) - elapsedSecsThisWeek(_time_)) // time at the start of the week for the given time
|
||||
#define nextSunday(_time_) (previousSunday(_time_)+SECS_PER_WEEK) // time at the end of the week for the given time
|
||||
|
||||
|
||||
/* Useful Macros for converting elapsed time to a time_t */
|
||||
#define minutesToTime_t ((M)) ( (M) * SECS_PER_MIN)
|
||||
#define hoursToTime_t ((H)) ( (H) * SECS_PER_HOUR)
|
||||
#define daysToTime_t ((D)) ( (D) * SECS_PER_DAY) // fixed on Jul 22 2011
|
||||
#define weeksToTime_t ((W)) ( (W) * SECS_PER_WEEK)
|
||||
|
||||
/*============================================================================*/
|
||||
/* time and date functions */
|
||||
int hour(); // the hour now
|
||||
int hour(time_t t); // the hour for the given time
|
||||
int hourFormat12(); // the hour now in 12 hour format
|
||||
int hourFormat12(time_t t); // the hour for the given time in 12 hour format
|
||||
uint8_t isAM(); // returns true if time now is AM
|
||||
uint8_t isAM(time_t t); // returns true the given time is AM
|
||||
uint8_t isPM(); // returns true if time now is PM
|
||||
uint8_t isPM(time_t t); // returns true the given time is PM
|
||||
int minute(); // the minute now
|
||||
int minute(time_t t); // the minute for the given time
|
||||
int second(); // the second now
|
||||
int second(time_t t); // the second for the given time
|
||||
int day(); // the day now
|
||||
int day(time_t t); // the day for the given time
|
||||
int weekday(); // the weekday now (Sunday is day 1)
|
||||
int weekday(time_t t); // the weekday for the given time
|
||||
int month(); // the month now (Jan is month 1)
|
||||
int month(time_t t); // the month for the given time
|
||||
int year(); // the full four digit year: (2009, 2010 etc)
|
||||
int year(time_t t); // the year for the given time
|
||||
|
||||
time_t now(); // return the current time as seconds since Jan 1 1970
|
||||
void setTime(time_t t);
|
||||
void setTime(int hr,int min,int sec,int day, int month, int yr);
|
||||
void adjustTime(long adjustment);
|
||||
|
||||
/* date strings */
|
||||
#define dt_MAX_STRING_LEN 9 // length of longest date string (excluding terminating null)
|
||||
char* monthStr(uint8_t month);
|
||||
char* dayStr(uint8_t day);
|
||||
char* monthShortStr(uint8_t month);
|
||||
char* dayShortStr(uint8_t day);
|
||||
|
||||
/* time sync functions */
|
||||
timeStatus_t timeStatus(); // indicates if time has been set and recently synchronized
|
||||
void setSyncProvider( getExternalTime getTimeFunction); // identify the external time provider
|
||||
void setSyncInterval(time_t interval); // set the number of seconds between re-sync
|
||||
|
||||
/* low level functions to convert to and from system time */
|
||||
void breakTime(time_t time, tmElements_t &tm); // break time_t into elements
|
||||
time_t makeTime(const tmElements_t &tm); // convert time elements into time_t
|
||||
|
||||
} // extern "C++"
|
||||
#endif // __cplusplus
|
||||
#endif /* _Time_h */
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For Time
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
time_t KEYWORD1
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
now KEYWORD2
|
||||
second KEYWORD2
|
||||
minute KEYWORD2
|
||||
hour KEYWORD2
|
||||
day KEYWORD2
|
||||
month KEYWORD2
|
||||
year KEYWORD2
|
||||
isAM KEYWORD2
|
||||
isPM KEYWORD2
|
||||
weekday KEYWORD2
|
||||
setTime KEYWORD2
|
||||
adjustTime KEYWORD2
|
||||
setSyncProvider KEYWORD2
|
||||
setSyncInterval KEYWORD2
|
||||
timeStatus KEYWORD2
|
||||
TimeLib KEYWORD2
|
||||
#######################################
|
||||
# Instances (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
@@ -1,26 +0,0 @@
|
||||
{
|
||||
"name": "Time",
|
||||
"description": "Time keeping library",
|
||||
"keywords": "Time, date, hour, minute, second, day, week, month, year, RTC",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Michael Margolis"
|
||||
},
|
||||
{
|
||||
"name": "Paul Stoffregen",
|
||||
"email": "paul@pjrc.com",
|
||||
"url": "http://www.pjrc.com",
|
||||
"maintainer": true
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PaulStoffregen/Time"
|
||||
},
|
||||
"version": "1.6.1",
|
||||
"homepage": "http://playground.arduino.cc/Code/Time",
|
||||
"frameworks": "Arduino",
|
||||
"examples": [
|
||||
"examples/*/*.ino"
|
||||
]
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
name=Time
|
||||
version=1.6.1
|
||||
author=Michael Margolis
|
||||
maintainer=Paul Stoffregen
|
||||
sentence=Timekeeping functionality for Arduino
|
||||
paragraph=Date and Time functions, with provisions to synchronize to external time sources like GPS and NTP (Internet). This library is often used together with TimeAlarms and DS1307RTC.
|
||||
category=Timing
|
||||
url=http://playground.arduino.cc/Code/Time/
|
||||
includes=TimeLib.h
|
||||
architectures=*
|
||||
|
||||
@@ -54,12 +54,7 @@ void NTPupdate() {
|
||||
time_t currentTime = getNtpTime();
|
||||
|
||||
if (currentTime) {
|
||||
rtc.setTime(currentTime);
|
||||
if(rx_rtc_avail) {
|
||||
RX8010SJ::DateTime rx_currenttime = RX8010SJ::DateTime();
|
||||
timeToDateTime(currentTime, &rx_currenttime);
|
||||
rx_rtc.writeDateTime(rx_currenttime);
|
||||
}
|
||||
set_time(currentTime);
|
||||
rtcset = true;
|
||||
NTPupdated = true;
|
||||
radio.rds.ctupdate = false;
|
||||
|
||||
206
src/TEF6686.cpp
206
src/TEF6686.cpp
@@ -1,13 +1,11 @@
|
||||
#include "TEF6686.h"
|
||||
#include <map>
|
||||
#include <Arduino.h>
|
||||
#include <TimeLib.h>
|
||||
#include <SPIFFS.h>
|
||||
#include "constants.h"
|
||||
#include "utils.h"
|
||||
|
||||
unsigned long rdstimer = 0;
|
||||
unsigned long bitStartTime = 0;
|
||||
uint8_t dropped_groups = 0;
|
||||
bool lastBitState = false;
|
||||
|
||||
uint16_t TEF6686::getBlockA(void) {
|
||||
@@ -25,13 +23,13 @@ void TEF6686::TestAFEON() {
|
||||
setMute();
|
||||
for (int x = 0; x < af_counter; x++) {
|
||||
timing = 0;
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Tune_To, 7, 3, af[x].frequency);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Tune_To, 4, 3, af[x].frequency);
|
||||
while (timing == 0 && !bitRead(timing, 15)) {
|
||||
devTEF_Radio_Get_Quality_Status(&status, &aflevel, &afusn, &afwam, &afoffset, NULL, NULL, NULL);
|
||||
timing = lowByte(status);
|
||||
}
|
||||
if (afoffset > -125 || afoffset < 125) {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Tune_To, 7, 4, af[x].frequency);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Tune_To, 4, 4, af[x].frequency);
|
||||
delay(187);
|
||||
devTEF_Radio_Get_RDS_Status(&rds.rdsStat, &rds.rdsA, &rds.rdsB, &rds.rdsC, &rds.rdsD, &rds.rdsErr);
|
||||
|
||||
@@ -47,7 +45,7 @@ void TEF6686::TestAFEON() {
|
||||
}
|
||||
}
|
||||
}
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Tune_To, 7, 4, currentfreq);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Tune_To, 4, 4, currentfreq);
|
||||
setUnMute();
|
||||
}
|
||||
|
||||
@@ -62,7 +60,7 @@ uint16_t TEF6686::TestAF() {
|
||||
|
||||
for (int x = 0; x < af_counter; x++) {
|
||||
timing = 0;
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Tune_To, 7, 3, af[x].frequency);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Tune_To, 4, 3, af[x].frequency);
|
||||
while (timing == 0 && !bitRead(timing, 15)) {
|
||||
devTEF_Radio_Get_Quality_Status(&status, &aflevel, &afusn, &afwam, &afoffset, NULL, NULL, NULL);
|
||||
timing = lowByte(status);
|
||||
@@ -82,7 +80,7 @@ uint16_t TEF6686::TestAF() {
|
||||
}
|
||||
|
||||
if (af_counter != 0 && af[highestIndex].afvalid && af[highestIndex].score > (currentlevel - currentusn - currentwam) && (af[highestIndex].score - (currentlevel - currentusn - currentwam)) >= 70) {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Tune_To, 7, 4, af[highestIndex].frequency);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Tune_To, 4, 4, af[highestIndex].frequency);
|
||||
delay(187);
|
||||
devTEF_Radio_Get_RDS_Status(&rds.rdsStat, &rds.rdsA, &rds.rdsB, &rds.rdsC, &rds.rdsD, &rds.rdsErr);
|
||||
if (bitRead(rds.rdsStat, 9)) {
|
||||
@@ -97,9 +95,9 @@ uint16_t TEF6686::TestAF() {
|
||||
af_counter = 0;
|
||||
} else {
|
||||
af[highestIndex].afvalid = false;
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Tune_To, 7, 4, currentfreq);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Tune_To, 4, 4, currentfreq);
|
||||
}
|
||||
} else devTEF_Set_Cmd(TEF_FM, Cmd_Tune_To, 7, 4, currentfreq);
|
||||
} else devTEF_Set_Cmd(TEF_FM, Cmd_Tune_To, 4, 4, currentfreq);
|
||||
}
|
||||
}
|
||||
return currentfreq;
|
||||
@@ -113,10 +111,11 @@ void TEF6686::init(byte TEF) {
|
||||
uint32_t clock = 12000000;
|
||||
|
||||
#ifndef DEEPELEC_DP_66X
|
||||
int xtalADC = analogRead(15);
|
||||
if (xtalADC < XTAL_0V_ADC + XTAL_ADC_TOL) clock = 9216000;
|
||||
else if (xtalADC > XTAL_1V_ADC - XTAL_ADC_TOL && xtalADC < XTAL_1V_ADC + XTAL_ADC_TOL);
|
||||
else if (xtalADC > XTAL_2V_ADC - XTAL_ADC_TOL && xtalADC < XTAL_2V_ADC + XTAL_ADC_TOL) clock = 55466670;
|
||||
int xtalMV = analogReadMilliVolts(15);
|
||||
|
||||
if (xtalMV < 0 + XTAL_MV_TOL) clock = 9216000;
|
||||
else if (xtalMV > 1000 - XTAL_MV_TOL && xtalMV < 1000 + XTAL_MV_TOL);
|
||||
else if (xtalMV > 2000 - XTAL_MV_TOL && xtalMV < 2000 + XTAL_MV_TOL) clock = 55466670;
|
||||
else clock = 4000000;
|
||||
#endif
|
||||
|
||||
@@ -124,26 +123,26 @@ void TEF6686::init(byte TEF) {
|
||||
Tuner_Patch(TEF);
|
||||
|
||||
// Start the firmware
|
||||
devTEF_Set_Cmd(TEF_INIT, 0, 3);
|
||||
devTEF_Set_Cmd(TEF_INIT, 0, 0);
|
||||
|
||||
while(devTEF_APPL_Get_Operation_Status() != 1) delay(5); // Wait for it to load
|
||||
|
||||
if(clock != 9216000) devTEF_Set_Cmd(TEF_APPL, Cmd_Set_ReferenceClock, 9, (clock >> 16) & 0xffff, clock & 0xffff, (clock == 55466670) ? 1 : 0);
|
||||
devTEF_Set_Cmd(TEF_APPL, Cmd_Set_Activate, 5, 1); // Setup done, start radio
|
||||
if(clock != 9216000) devTEF_Set_Cmd(TEF_APPL, Cmd_Set_ReferenceClock, 6, (clock >> 16) & 0xffff, clock & 0xffff, (clock == 55466670) ? 1 : 0);
|
||||
devTEF_Set_Cmd(TEF_APPL, Cmd_Set_Activate, 2, 1); // Setup done, start radio
|
||||
|
||||
while(devTEF_APPL_Get_Operation_Status() != 2) delay(5); // Wait for it to start
|
||||
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Highcut_Mph, 9, 0, 360, 300);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Highcut_Max, 7, 0, 4000);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_LowCut_Max, 7, 0, 100);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Stereo_Time, 11, 60, 120, 100, 200);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StHiBlend_Time, 11, 500, 2000, 200, 200);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StHiBlend_Level, 9, 0, 600, 240);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StHiBlend_Noise, 9, 0, 160, 140);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StHiBlend_Mph, 9, 0, 160, 140);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StHiBlend_Max, 7, 0, 4000);
|
||||
devTEF_Set_Cmd(TEF_AUDIO, Cmd_Set_Ana_Out, 7, 128, 1);
|
||||
devTEF_Set_Cmd(TEF_AUDIO, Cmd_Set_Output_Source, 7, 128, 224);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Highcut_Mph, 6, 0, 360, 300);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Highcut_Max, 4, 0, 4000);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_LowCut_Max, 4, 0, 100);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Stereo_Time, 8, 60, 120, 100, 200);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StHiBlend_Time, 8, 500, 2000, 200, 200);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StHiBlend_Level, 6, 0, 600, 240);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StHiBlend_Noise, 6, 0, 160, 140);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StHiBlend_Mph, 6, 0, 160, 140);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StHiBlend_Max, 4, 0, 4000);
|
||||
devTEF_Set_Cmd(TEF_AUDIO, Cmd_Set_Ana_Out, 4, 128, 1);
|
||||
devTEF_Set_Cmd(TEF_AUDIO, Cmd_Set_Output_Source, 4, 128, 224);
|
||||
}
|
||||
|
||||
void TEF6686::getIdentification(uint16_t *device, uint16_t *hw_version, uint16_t *sw_version) {
|
||||
@@ -156,73 +155,73 @@ void TEF6686::getIdentification(uint16_t *device, uint16_t *hw_version, uint16_t
|
||||
}
|
||||
|
||||
void TEF6686::power(bool mode) {
|
||||
devTEF_Set_Cmd(TEF_APPL, Cmd_Set_OperationMode, 5, mode);
|
||||
if (mode == 0) devTEF_Set_Cmd(TEF_FM, Cmd_Tune_To, 7, 1, 10000);
|
||||
devTEF_Set_Cmd(TEF_APPL, Cmd_Set_OperationMode, 2, mode);
|
||||
if (mode == 0) devTEF_Set_Cmd(TEF_FM, Cmd_Tune_To, 4, 1, 10000);
|
||||
}
|
||||
|
||||
void TEF6686::extendBW(bool yesno) {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Bandwidth_Options, 5, (yesno ? 400 : 950));
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Bandwidth_Options, 2, (yesno ? 400 : 950));
|
||||
}
|
||||
|
||||
void TEF6686::SetFreq(uint16_t frequency) {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Tune_To, 7, 4, frequency);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Tune_To, 4, 4, frequency);
|
||||
currentfreq = ((frequency + 5) / 10) * 10;
|
||||
currentfreq2 = frequency;
|
||||
}
|
||||
|
||||
void TEF6686::SetFreqAM(uint16_t frequency) {
|
||||
devTEF_Set_Cmd(TEF_AM, Cmd_Tune_To, 7, 1, frequency);
|
||||
devTEF_Set_Cmd(TEF_AM, Cmd_Tune_To, 4, 1, frequency);
|
||||
}
|
||||
|
||||
void TEF6686::setOffset(int8_t offset) {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_LevelOffset, 5, (offset * 10) - 70);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_LevelOffset, 2, (offset * 10) - 70);
|
||||
}
|
||||
|
||||
void TEF6686::setAMOffset(int8_t offset) {
|
||||
devTEF_Set_Cmd(TEF_AM, Cmd_Set_LevelOffset, 5, (offset * 10) - 70);
|
||||
devTEF_Set_Cmd(TEF_AM, Cmd_Set_LevelOffset, 2, (offset * 10) - 70);
|
||||
}
|
||||
|
||||
void TEF6686::setFMBandw(uint16_t bandwidth) {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Bandwidth, 7, 0, bandwidth * 10);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Bandwidth, 4, 0, bandwidth * 10);
|
||||
}
|
||||
|
||||
void TEF6686::setAMBandw(uint16_t bandwidth) {
|
||||
devTEF_Set_Cmd(TEF_AM, Cmd_Set_Bandwidth, 7, 0, bandwidth * 10);
|
||||
devTEF_Set_Cmd(TEF_AM, Cmd_Set_Bandwidth, 4, 0, bandwidth * 10);
|
||||
}
|
||||
|
||||
void TEF6686::setAMCoChannel(uint16_t start, uint8_t level) {
|
||||
uint8_t mode = 1;
|
||||
if(start == 0) mode = 0;
|
||||
devTEF_Set_Cmd(TEF_AM, Cmd_Set_CoChannelDet, 11, mode, 2, start * 10, 1000, level);
|
||||
devTEF_Set_Cmd(TEF_AM, Cmd_Set_CoChannelDet, 8, mode, 2, start * 10, 1000, level);
|
||||
}
|
||||
|
||||
void TEF6686::setSoftmuteAM(uint8_t mode) {
|
||||
devTEF_Set_Cmd(TEF_AM, Cmd_Set_Softmute_Max, 7, mode, 250);
|
||||
devTEF_Set_Cmd(TEF_AM, Cmd_Set_Softmute_Max, 4, mode, 250);
|
||||
}
|
||||
|
||||
void TEF6686::setSoftmuteFM(uint8_t mode) {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Softmute_Max, 7, mode, 200);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Softmute_Max, 4, mode, 200);
|
||||
}
|
||||
|
||||
void TEF6686::setAMNoiseBlanker(uint16_t start) {
|
||||
devTEF_Set_Cmd(TEF_AM, Cmd_Set_NoiseBlanker, 7, (start == 0) ? 0 : 1, (start == 0) ? 1000 : start * 10);
|
||||
devTEF_Set_Cmd(TEF_AM, Cmd_Set_NoiseBlanker_Audio, 7, (start == 0) ? 0 : 1, 1000);
|
||||
devTEF_Set_Cmd(TEF_AM, Cmd_Set_NoiseBlanker, 4, (start == 0) ? 0 : 1, (start == 0) ? 1000 : start * 10);
|
||||
devTEF_Set_Cmd(TEF_AM, Cmd_Set_NoiseBlanker_Audio, 4, (start == 0) ? 0 : 1, 1000);
|
||||
}
|
||||
|
||||
void TEF6686::setAMAttenuation(uint16_t start) {
|
||||
devTEF_Set_Cmd(TEF_AM, Cmd_Set_Antenna, 5, start * 10);
|
||||
devTEF_Set_Cmd(TEF_AM, Cmd_Set_Antenna, 2, start * 10);
|
||||
}
|
||||
|
||||
void TEF6686::setFMABandw() {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Bandwidth, 7, 1, 3110);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Bandwidth, 4, 1, 3110);
|
||||
}
|
||||
|
||||
void TEF6686::setiMS(bool mph) {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_MphSuppression, 5, mph);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_MphSuppression, 2, mph);
|
||||
}
|
||||
|
||||
void TEF6686::setEQ(bool eq) {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_ChannelEqualizer, 5, eq);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_ChannelEqualizer, 2, eq);
|
||||
}
|
||||
|
||||
bool TEF6686::getStereoStatus() {
|
||||
@@ -233,109 +232,109 @@ bool TEF6686::getStereoStatus() {
|
||||
}
|
||||
|
||||
void TEF6686::setMono(bool mono) {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Stereo_Min, 7, mono ? 2 : 0);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Stereo_Min, 4, mono ? 2 : 0);
|
||||
}
|
||||
|
||||
void TEF6686::setVolume(int8_t volume) {
|
||||
devTEF_Set_Cmd(TEF_AUDIO, Cmd_Set_Volume, 5, volume * 10);
|
||||
devTEF_Set_Cmd(TEF_AUDIO, Cmd_Set_Volume, 2, volume * 10);
|
||||
}
|
||||
|
||||
void TEF6686::setMute() {
|
||||
mute = true;
|
||||
if (mpxmode) devTEF_Set_Cmd(TEF_FM, Cmd_Set_Specials, 5, 0);
|
||||
devTEF_Set_Cmd(TEF_AUDIO, Cmd_Set_Mute, 5, 1);
|
||||
if (mpxmode) devTEF_Set_Cmd(TEF_FM, Cmd_Set_Specials, 2, 0);
|
||||
devTEF_Set_Cmd(TEF_AUDIO, Cmd_Set_Mute, 2, 1);
|
||||
}
|
||||
|
||||
void TEF6686::setUnMute() {
|
||||
mute = false;
|
||||
if (mpxmode) devTEF_Set_Cmd(TEF_FM, Cmd_Set_Specials, 5, 1);
|
||||
devTEF_Set_Cmd(TEF_AUDIO, Cmd_Set_Mute, 5, 0);
|
||||
if (mpxmode) devTEF_Set_Cmd(TEF_FM, Cmd_Set_Specials, 2, 1);
|
||||
devTEF_Set_Cmd(TEF_AUDIO, Cmd_Set_Mute, 2, 0);
|
||||
}
|
||||
|
||||
void TEF6686::setAGC(uint8_t agc) {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_RFAGC, 7, agc * 10, 0);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_RFAGC, 4, agc * 10, 0);
|
||||
}
|
||||
|
||||
void TEF6686::setAMAGC(uint8_t agc) {
|
||||
devTEF_Set_Cmd(TEF_AM, Cmd_Set_RFAGC, 7, agc * 10, 0);
|
||||
devTEF_Set_Cmd(TEF_AM, Cmd_Set_RFAGC, 4, agc * 10, 0);
|
||||
}
|
||||
|
||||
void TEF6686::setDeemphasis(uint8_t timeconstant) {
|
||||
switch (timeconstant) {
|
||||
case 1: devTEF_Set_Cmd(TEF_FM, Cmd_Set_Deemphasis, 5, 500); break;
|
||||
case 2: devTEF_Set_Cmd(TEF_FM, Cmd_Set_Deemphasis, 5, 750); break;
|
||||
default: devTEF_Set_Cmd(TEF_FM, Cmd_Set_Deemphasis, 5, 0); break;
|
||||
case 1: devTEF_Set_Cmd(TEF_FM, Cmd_Set_Deemphasis, 2, 500); break;
|
||||
case 2: devTEF_Set_Cmd(TEF_FM, Cmd_Set_Deemphasis, 2, 750); break;
|
||||
default: devTEF_Set_Cmd(TEF_FM, Cmd_Set_Deemphasis, 2, 0); break;
|
||||
}
|
||||
}
|
||||
|
||||
void TEF6686::setAudio(uint8_t audio) {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Specials, 5, audio);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Specials, 2, audio);
|
||||
mpxmode = (audio != 0);
|
||||
}
|
||||
|
||||
void TEF6686::setFMSI(uint8_t mode) {
|
||||
if(mode > 2) mode = 2;
|
||||
if(mode < 1) mode = 1;
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StereoImprovement, 5, mode-1);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StereoImprovement, 2, mode-1);
|
||||
}
|
||||
|
||||
void TEF6686::setFMSI_Time(uint16_t attack, uint16_t decay) {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StBandBlend_Time, 7, attack, decay);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StBandBlend_Time, 4, attack, decay);
|
||||
}
|
||||
|
||||
void TEF6686::setFMSI_Gain(uint16_t band1, uint16_t band2, uint16_t band3, uint16_t band4) {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StBandBlend_Gain, 11, band1 * 10, band2 * 10, band3 * 10, band4 * 10);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StBandBlend_Gain, 8, band1 * 10, band2 * 10, band3 * 10, band4 * 10);
|
||||
}
|
||||
|
||||
void TEF6686::setFMSI_Bias(int16_t band1, int16_t band2, int16_t band3, int16_t band4) {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StBandBlend_Bias, 11, band1 - 250, band2 - 250, band3 - 250, band4 - 250);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StBandBlend_Bias, 8, band1 - 250, band2 - 250, band3 - 250, band4 - 250);
|
||||
}
|
||||
|
||||
void TEF6686::setFMNoiseBlanker(uint16_t start) {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_NoiseBlanker, 7, (start == 0) ? 0 : 1, (start == 0) ? 1000 : (start * 10));
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_NoiseBlanker, 4, (start == 0) ? 0 : 1, (start == 0) ? 1000 : (start * 10));
|
||||
}
|
||||
|
||||
void TEF6686::setStereoLevel(uint8_t start) {
|
||||
if (start == 0) {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Stereo_Level, 9, 0, start * 10, 60);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Stereo_Noise, 9, 0, 240, 200);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Stereo_Mph, 9, 0, 240, 200);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Stereo_Level, 6, 0, start * 10, 60);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Stereo_Noise, 6, 0, 240, 200);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Stereo_Mph, 6, 0, 240, 200);
|
||||
} else {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Stereo_Level, 9, 3, start * 10, 60);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Stereo_Noise, 9, 3, 240, 200);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Stereo_Mph, 9, 3, 240, 200);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Stereo_Level, 6, 3, start * 10, 60);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Stereo_Noise, 6, 3, 240, 200);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Stereo_Mph, 6, 3, 240, 200);
|
||||
}
|
||||
}
|
||||
|
||||
void TEF6686::setHighCutOffset(uint8_t start) {
|
||||
if (start == 0) {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Highcut_Level, 9, 0, start * 10, 300);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Highcut_Noise, 9, 0, 360, 300);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Highcut_Mph, 9, 0, 360, 300);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Highcut_Level, 6, 0, start * 10, 300);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Highcut_Noise, 6, 0, 360, 300);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Highcut_Mph, 6, 0, 360, 300);
|
||||
} else {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Highcut_Level, 9, 3, start * 10, 300);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Highcut_Noise, 9, 3, 360, 300);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Highcut_Mph, 9, 3, 360, 300);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Highcut_Level, 6, 3, start * 10, 300);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Highcut_Noise, 6, 3, 360, 300);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Highcut_Mph, 6, 3, 360, 300);
|
||||
}
|
||||
}
|
||||
|
||||
void TEF6686::setHighCutLevel(uint16_t limit) {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Highcut_Max, 7, 1, limit * 100);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_Highcut_Max, 4, 1, limit * 100);
|
||||
}
|
||||
|
||||
void TEF6686::setStHiBlendLevel(uint16_t limit) {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StHiBlend_Max, 7, 1, limit * 100);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StHiBlend_Max, 4, 1, limit * 100);
|
||||
}
|
||||
|
||||
void TEF6686::setStHiBlendOffset(uint8_t start) {
|
||||
if (start == 0) {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StHiBlend_Level, 9, 0, start * 10, 300);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StHiBlend_Noise, 9, 0, 360, 300);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StHiBlend_Mph, 9, 0, 360, 300);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StHiBlend_Level, 6, 0, start * 10, 300);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StHiBlend_Noise, 6, 0, 360, 300);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StHiBlend_Mph, 6, 0, 360, 300);
|
||||
} else {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StHiBlend_Level, 9, 3, start * 10, 300);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StHiBlend_Noise, 9, 3, 360, 300);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StHiBlend_Mph, 9, 3, 360, 300);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StHiBlend_Level, 6, 3, start * 10, 300);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StHiBlend_Noise, 6, 3, 360, 300);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_StHiBlend_Mph, 6, 3, 360, 300);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,23 +359,19 @@ void TEF6686::getStatusAM(int16_t *level, uint16_t *noise, uint16_t *cochannel,
|
||||
void TEF6686::readRDS(byte showrdserrors) {
|
||||
if(rds.filter && ps_process) devTEF_Radio_Get_RDS_Status(&rds.rdsStat, &rds.rdsA, &rds.rdsB, &rds.rdsC, &rds.rdsD, &rds.rdsErr);
|
||||
else {
|
||||
if(millis() >= rdstimer + 87) {
|
||||
rdstimer += 87;
|
||||
for(int i = 0; i < 3; i++) {
|
||||
devTEF_Radio_Get_RDS_Data(&rds.rdsStat, &rds.rdsA, &rds.rdsB, &rds.rdsC, &rds.rdsD, &rds.rdsErr);
|
||||
|
||||
if(bitRead(rds.rdsStat, 14)) {
|
||||
for (int i = 0; i < 22; i++) devTEF_Radio_Get_RDS_Data(&rds.rdsStat, &rds.rdsA, &rds.rdsB, &rds.rdsC, &rds.rdsD, &rds.rdsErr);
|
||||
}
|
||||
delay(2);
|
||||
if(bitRead(rds.rdsStat, 15)) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(bitRead(rds.rdsStat, 9)) {
|
||||
rds.hasRDS = true;
|
||||
bitStartTime = 0;
|
||||
dropped_groups = 0;
|
||||
} else {
|
||||
if(bitStartTime == 0) bitStartTime = millis();
|
||||
else if(millis() - bitStartTime >= 87) rds.hasRDS = false;
|
||||
if(dropped_groups > 7) rds.hasRDS = false;
|
||||
dropped_groups++;
|
||||
return; // No sync means no data, ever! Unless sync status changes of course
|
||||
}
|
||||
|
||||
@@ -1215,18 +1210,18 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
|
||||
if (rds.rdsD == 0x4BD7) {
|
||||
rds.hasRTplus = true;
|
||||
rtplusblock = ((rds.rdsB & 0x1F) >> 1) * 2;
|
||||
rtplusblock = rds.rdsB & 0x1E;
|
||||
}
|
||||
|
||||
if (rds.rdsD == 0x0093) {
|
||||
rds.hasDABAF = true;
|
||||
DABAFblock = ((rds.rdsB & 0x1F) >> 1) * 2;
|
||||
DABAFblock = rds.rdsB & 0x1E;
|
||||
}
|
||||
|
||||
if (rds.rdsD == 0x6552) {
|
||||
_hasEnhancedRT = true;
|
||||
eRTblock = ((rds.rdsB & 0x1F) >> 1) * 2;
|
||||
eRTcoding = bitRead(rds.rdsC, 0);
|
||||
eRTblock = rds.rdsB & 0x1E;
|
||||
eRTcoding = rds.rdsC & 1;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
@@ -1250,11 +1245,11 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
if ((M + 2 - (12 * J)) < 13) month = M + 2 - (12 * J);
|
||||
if ((100 * (C - 49) + Y + J) > 2022) year = 100 * (C - 49) + Y + J;
|
||||
|
||||
hour = ((rds.rdsD >> 12) & 0xf) | ((rds.rdsC << 4) & 0x10);
|
||||
timeoffset = rds.rdsD & 0x001f;
|
||||
hour = ((rds.rdsD >> 12) & 0xF) | ((rds.rdsC << 4) & 0x10);
|
||||
timeoffset = rds.rdsD & 0x1F;
|
||||
if (bitRead(rds.rdsD, 5)) timeoffset *= -1;
|
||||
timeoffset *= 1800;
|
||||
minute = (rds.rdsD & 0x0fc0) >> 6;
|
||||
minute = (rds.rdsD & 0xFC0) >> 6;
|
||||
|
||||
if (year < 2026 || hour > 23 || minute > 59 || timeoffset > 55800 || timeoffset < -55800) break;
|
||||
|
||||
@@ -1279,8 +1274,7 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
|
||||
if (!NTPupdated) {
|
||||
time_t corrected_time = rds_utc_time - (current_correction / 2);
|
||||
rtc.setTime(corrected_time);
|
||||
sync_to_rx_rtc();
|
||||
set_time(corrected_time);
|
||||
}
|
||||
} else rds.hasCT = false;
|
||||
lastrdstime = rdstime;
|
||||
@@ -1562,7 +1556,7 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
}
|
||||
|
||||
void TEF6686::clearRDS(bool fullsearchrds) {
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_RDS, 9, fullsearchrds ? 3 : 1, 1, 0);
|
||||
devTEF_Set_Cmd(TEF_FM, Cmd_Set_RDS, 6, fullsearchrds ? 3 : 1, 1, 0);
|
||||
rds.piBuffer.clear();
|
||||
rds.stationName = rds.stationText = rds.stationNameLong = "";
|
||||
rds.PTYN = rds.stationText32 = rds.RTContent1 = rds.RTContent2 = "";;
|
||||
@@ -1648,7 +1642,7 @@ void TEF6686::clearRDS(bool fullsearchrds) {
|
||||
}
|
||||
|
||||
void TEF6686::tone(uint16_t time, int16_t amplitude, uint16_t frequency) {
|
||||
devTEF_Set_Cmd(TEF_AUDIO, Cmd_Set_Mute, 5, 0);
|
||||
devTEF_Set_Cmd(TEF_AUDIO, Cmd_Set_Mute, 2, 0);
|
||||
devTEF_Radio_Set_Wavegen(1, amplitude, frequency);
|
||||
delay(time);
|
||||
devTEF_Radio_Set_Wavegen(0, 0, 0);
|
||||
@@ -1697,10 +1691,10 @@ void TEF6686::RDScharConverter(const char* input, wchar_t* output, size_t size,
|
||||
case 0x9B: output[i] = L'ç'; break;
|
||||
case 0x9C: output[i] = L'ş'; break;
|
||||
case 0x9D: output[i] = L'ǧ'; break;
|
||||
case 0x9E: output[i] = L'ı'; break;
|
||||
case 0x9E: output[i] = L'\x131'; break;
|
||||
case 0x9F: output[i] = L'ij'; break;
|
||||
case 0xA0: output[i] = L'ª'; break;
|
||||
case 0xA1: output[i] = L'α'; break;
|
||||
case 0xA1: output[i] = L'\x3b1'; break;
|
||||
case 0xA2: output[i] = L'©'; break;
|
||||
case 0xA3: output[i] = L'‰'; break;
|
||||
case 0xA4: output[i] = L'Ǧ'; break;
|
||||
|
||||
@@ -10,14 +10,14 @@ void devTEF_Set_Cmd(TEF_MODULE module, uint8_t cmd, uint16_t len, ...) {
|
||||
buf[1] = cmd;
|
||||
buf[2] = 1;
|
||||
|
||||
for (i = 3; i < len; i++) {
|
||||
for (i = 0; i < len; i++) {
|
||||
temp = va_arg(vArgs, int);
|
||||
buf[i++] = High_16bto8b(temp);
|
||||
buf[i] = Low_16bto8b(temp);
|
||||
buf[3 + i++] = High_16bto8b(temp);
|
||||
buf[3 + i] = Low_16bto8b(temp);
|
||||
}
|
||||
|
||||
va_end(vArgs);
|
||||
Tuner_WriteBuffer(buf, len);
|
||||
Tuner_WriteBuffer(buf, len + 3);
|
||||
}
|
||||
|
||||
bool devTEF_Get_Cmd(TEF_MODULE module, uint8_t cmd, uint8_t *receive, uint16_t len) {
|
||||
@@ -32,25 +32,10 @@ bool devTEF_Get_Cmd(TEF_MODULE module, uint8_t cmd, uint8_t *receive, uint16_t l
|
||||
|
||||
uint8_t devTEF_APPL_Get_Operation_Status() {
|
||||
uint8_t buf[2];
|
||||
while(!devTEF_Get_Cmd(TEF_APPL, Cmd_Get_Operation_Status, buf, sizeof(buf))) delay(1);
|
||||
while(!devTEF_Get_Cmd(TEF_APPL, Cmd_Get_Operation_Status, buf, sizeof(buf))) delay(2);
|
||||
return Convert8bto16b(buf);
|
||||
}
|
||||
|
||||
bool devTEF_Radio_Get_Processing_Status(uint16_t *highcut, uint16_t *stereo, uint16_t *sthiblend, uint8_t *stband_1, uint8_t *stband_2, uint8_t *stband_3, uint8_t *stband_4) {
|
||||
uint8_t buf[12];
|
||||
uint16_t r = devTEF_Get_Cmd(TEF_FM, Cmd_Get_Processing_Status, buf, sizeof(buf));
|
||||
*highcut = Convert8bto16b(buf + 2) / 10;
|
||||
*stereo = Convert8bto16b(buf + 4) / 10;
|
||||
*sthiblend = Convert8bto16b(buf + 6) / 10;
|
||||
uint16_t stband_1_2 = Convert8bto16b(buf + 8);
|
||||
uint16_t stband_3_4 = Convert8bto16b(buf + 10);
|
||||
*stband_1 = High_16bto8b(stband_1_2);
|
||||
*stband_2 = Low_16bto8b(stband_1_2);
|
||||
*stband_3 = High_16bto8b(stband_3_4);
|
||||
*stband_4 = Low_16bto8b(stband_3_4);
|
||||
return r;
|
||||
}
|
||||
|
||||
void devTEF_Radio_Get_Quality_Status(uint16_t *status, int16_t *level, uint16_t *usn, uint16_t *wam, int16_t *offset, uint16_t *bandwidth, uint16_t *mod, int8_t *snr) {
|
||||
uint8_t buf[14];
|
||||
devTEF_Get_Cmd(TEF_FM, Cmd_Get_Quality_Data, buf, sizeof(buf));
|
||||
@@ -77,16 +62,15 @@ void devTEF_Radio_Get_RDS_Status(uint16_t *status, uint16_t *A_block, uint16_t *
|
||||
if(dec_error != NULL) *dec_error = Convert8bto16b(buf + 10);
|
||||
}
|
||||
|
||||
bool devTEF_Radio_Get_RDS_Data(uint16_t *status, uint16_t *A_block, uint16_t *B_block, uint16_t *C_block, uint16_t *D_block, uint16_t *dec_error) {
|
||||
void devTEF_Radio_Get_RDS_Data(uint16_t *status, uint16_t *A_block, uint16_t *B_block, uint16_t *C_block, uint16_t *D_block, uint16_t *dec_error) {
|
||||
uint8_t buf[12];
|
||||
uint8_t r = devTEF_Get_Cmd(TEF_FM, Cmd_Get_RDS_Data, buf, sizeof(buf));
|
||||
*status = Convert8bto16b(buf);
|
||||
*A_block = Convert8bto16b(buf + 2);
|
||||
*B_block = Convert8bto16b(buf + 4);
|
||||
*C_block = Convert8bto16b(buf + 6);
|
||||
*D_block = Convert8bto16b(buf + 8);
|
||||
*dec_error = Convert8bto16b(buf + 10);
|
||||
return r;
|
||||
devTEF_Get_Cmd(TEF_FM, Cmd_Get_RDS_Data, buf, sizeof(buf));
|
||||
if(status != NULL) *status = Convert8bto16b(buf);
|
||||
if(A_block != NULL) *A_block = Convert8bto16b(buf + 2);
|
||||
if(B_block != NULL) *B_block = Convert8bto16b(buf + 4);
|
||||
if(C_block != NULL) *C_block = Convert8bto16b(buf + 6);
|
||||
if(D_block != NULL) *D_block = Convert8bto16b(buf + 8);
|
||||
if(dec_error != NULL) *dec_error = Convert8bto16b(buf + 10);
|
||||
}
|
||||
|
||||
bool devTEF_Radio_Get_Stereo_Status(uint16_t *status) {
|
||||
@@ -98,7 +82,7 @@ bool devTEF_Radio_Get_Stereo_Status(uint16_t *status) {
|
||||
}
|
||||
|
||||
void devTEF_Radio_Set_Wavegen(bool mode, int16_t amplitude, uint16_t freq) {
|
||||
devTEF_Set_Cmd(TEF_AUDIO, Cmd_Set_Input, 5, mode ? 240 : 0);
|
||||
if (mode) devTEF_Set_Cmd(TEF_AUDIO, Cmd_Set_WaveGen, 15, 5, 0, amplitude * 10, freq, amplitude * 10, freq);
|
||||
else devTEF_Set_Cmd(TEF_AUDIO, Cmd_Set_WaveGen, 15, 0);
|
||||
devTEF_Set_Cmd(TEF_AUDIO, Cmd_Set_Input, 2, mode ? 240 : 0);
|
||||
if (mode) devTEF_Set_Cmd(TEF_AUDIO, Cmd_Set_WaveGen, 12, 5, 0, amplitude * 10, freq, amplitude * 10, freq);
|
||||
else devTEF_Set_Cmd(TEF_AUDIO, Cmd_Set_WaveGen, 12, 0);
|
||||
}
|
||||
@@ -9,7 +9,7 @@ bool Tuner_WriteBuffer(unsigned char *buf, uint16_t len) {
|
||||
Wire.beginTransmission(TEF668X_ADDRESS);
|
||||
for (uint16_t i = 0; i < len; i++) Wire.write(buf[i]);
|
||||
uint8_t r = Wire.endTransmission();
|
||||
if (!Data_Accelerator) delay(1);
|
||||
if (!Data_Accelerator) delay(2);
|
||||
return (r == 0) ? true : false;
|
||||
}
|
||||
|
||||
|
||||
@@ -406,9 +406,11 @@ void sendUDPlog() {
|
||||
String CHIP = "";
|
||||
switch (chipmodel) {
|
||||
case 0: CHIP = "TEF6686"; break;
|
||||
#ifndef DEEPELEC_DP_66X
|
||||
case 1: CHIP = "TEF6687"; break;
|
||||
case 2: CHIP = "TEF6688"; break;
|
||||
case 3: CHIP = "TEF6689"; break;
|
||||
#endif
|
||||
}
|
||||
|
||||
String RTPLUS = "";
|
||||
|
||||
77
src/main.cpp
77
src/main.cpp
@@ -4,7 +4,6 @@
|
||||
#include <Wire.h>
|
||||
#include <Hash.h>
|
||||
#include <FS.h>
|
||||
#include <TimeLib.h>
|
||||
using fs::FS;
|
||||
#include <SPIFFS.h>
|
||||
#include "NTPupdate.h"
|
||||
@@ -252,7 +251,7 @@ void SetTunerPatch() {
|
||||
EEPROM.writeByte(EE_BYTE_TEF, TEF);
|
||||
EEPROM.commit();
|
||||
Tuner_Reset();
|
||||
ESP.restart();
|
||||
esp_restart();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1159,11 +1158,12 @@ void setup() {
|
||||
|
||||
Wire.begin();
|
||||
Wire.setClock(400000);
|
||||
delay(5);
|
||||
delay(3);
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
byte error, address;
|
||||
for (address = 1; address < 127; address++) {
|
||||
for (address = 1; address < 108; address++) {
|
||||
Wire.beginTransmission(address);
|
||||
error = Wire.endTransmission();
|
||||
|
||||
@@ -1175,6 +1175,8 @@ void setup() {
|
||||
Serial.print(" RTC");
|
||||
rx_rtc_avail = true;
|
||||
}
|
||||
else if(address == TEF668X_ADDRESS) Serial.print(" TEF");
|
||||
else if(address == XL9555_ADDRESS) Serial.print(" GPIO");
|
||||
Serial.println(" !");
|
||||
} else if (error == 4) {
|
||||
Serial.print("Unknown error at 0x");
|
||||
@@ -1182,21 +1184,19 @@ void setup() {
|
||||
Serial.println(address, HEX);
|
||||
}
|
||||
}
|
||||
Serial.flush();
|
||||
Serial.end();
|
||||
|
||||
rtc.setTime(0);
|
||||
if(rx_rtc_avail) {
|
||||
RX8010SJ::DateTime defaulttime = RX8010SJ::DateTime();
|
||||
defaulttime.second = 21;
|
||||
defaulttime.minute = 45;
|
||||
defaulttime.hour = 11;
|
||||
defaulttime.dayOfWeek = 6;
|
||||
defaulttime.dayOfMonth = 11;
|
||||
defaulttime.month = 1;
|
||||
defaulttime.year = 26;
|
||||
bool reset = rx_rtc.initModule(); // initModule, not initAdapter, adapter also reinits wire
|
||||
if(reset) {
|
||||
RX8010SJ::DateTime defaulttime = RX8010SJ::DateTime();
|
||||
defaulttime.second = 00;
|
||||
defaulttime.minute = 00;
|
||||
defaulttime.hour = 18;
|
||||
defaulttime.dayOfWeek = 1;
|
||||
defaulttime.dayOfMonth = 13;
|
||||
defaulttime.month = 1;
|
||||
defaulttime.year = 26;
|
||||
Serial.println("RTC reset with defaults");
|
||||
rx_rtc.writeDateTime(defaulttime);
|
||||
} else {
|
||||
@@ -1205,6 +1205,9 @@ void setup() {
|
||||
}
|
||||
}
|
||||
|
||||
Serial.flush();
|
||||
Serial.end();
|
||||
|
||||
EEPROM.begin(EE_TOTAL_CNT);
|
||||
loadData();
|
||||
|
||||
@@ -1408,7 +1411,7 @@ void setup() {
|
||||
Infoboxprint(textUI(66));
|
||||
tftPrint(ACENTER, textUI(2), 155, 130, ActiveColor, ActiveColorSmooth, 28);
|
||||
while (digitalRead(ROTARY_BUTTON) == LOW && digitalRead(BWBUTTON) == LOW) delay(50);
|
||||
ESP.restart();
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
if (digitalRead(BWBUTTON) == LOW && digitalRead(ROTARY_BUTTON) == HIGH && digitalRead(MODEBUTTON) == LOW && digitalRead(BANDBUTTON) == HIGH) {
|
||||
@@ -1439,7 +1442,7 @@ void setup() {
|
||||
|
||||
tft.fillScreen(BackgroundColor);
|
||||
tftPrint(ACENTER, textUI(8), 160, 3, PrimaryColor, PrimaryColorSmooth, 28);
|
||||
tftPrint(ACENTER, "Software " + String(VERSION), 160, 152, PrimaryColor, PrimaryColorSmooth, 16);
|
||||
tftPrint(ACENTER, "Firmware " + String(VERSION), 160, 152, PrimaryColor, PrimaryColorSmooth, 16);
|
||||
|
||||
tft.fillRect(120, 230, 16, 6, GreyoutColor);
|
||||
tft.fillRect(152, 230, 16, 6, GreyoutColor);
|
||||
@@ -1492,7 +1495,7 @@ void setup() {
|
||||
tft.fillRect(152, 230, 16, 6, SignificantColor);
|
||||
while (true);
|
||||
}
|
||||
tftPrint(ACENTER, "Patch: v" + String(TEF), 160, 202, ActiveColor, ActiveColorSmooth, 28);
|
||||
tftPrint(ACENTER, "Patch: v" + String(TEF) + " HW " + String(hw >> 8) + "." + String(hw & 0xff) + " SW " + String(sw >> 8) + "." + String(sw & 0xff), 160, 202, ActiveColor, ActiveColorSmooth, 16);
|
||||
|
||||
// Configures the GPIO chip for input in every pin
|
||||
Wire.beginTransmission(XL9555_ADDRESS);
|
||||
@@ -1507,14 +1510,14 @@ void setup() {
|
||||
if (wifi) {
|
||||
tryWiFi();
|
||||
tft.fillRect(184, 230, 16, 6, PrimaryColor);
|
||||
delay(2000);
|
||||
delay(1750);
|
||||
} else {
|
||||
Server.end();
|
||||
Udp.stop();
|
||||
tft.fillRect(184, 230, 16, 6, SignificantColor);
|
||||
}
|
||||
|
||||
while(digitalRead(ROTARY_BUTTON) == LOW) delay(50);
|
||||
while(digitalRead(ROTARY_BUTTON) == LOW) delay(75);
|
||||
|
||||
radio.setVolume(VolSet);
|
||||
radio.setOffset(LevelOffset);
|
||||
@@ -2035,7 +2038,6 @@ void DivdeSWMIBand() {
|
||||
}
|
||||
SWMIBandPos = SW_MI_BAND_GAP;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ToggleSWMIBand(bool frequencyup) {
|
||||
@@ -4044,4 +4046,39 @@ uint8_t doAutoMemory(uint16_t startfreq, uint16_t stopfreq, uint8_t startmem, ui
|
||||
SQ = false;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_task_wdt.h"
|
||||
|
||||
#ifndef ARDUINO_LOOP_STACK_SIZE
|
||||
#ifndef CONFIG_ARDUINO_LOOP_STACK_SIZE
|
||||
#define ARDUINO_LOOP_STACK_SIZE 8192
|
||||
#else
|
||||
#define ARDUINO_LOOP_STACK_SIZE CONFIG_ARDUINO_LOOP_STACK_SIZE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
TaskHandle_t loopTaskHandle = NULL;
|
||||
|
||||
bool loopTaskWDTEnabled;
|
||||
|
||||
__attribute__((weak)) size_t getArduinoLoopTaskStackSize(void) {
|
||||
return ARDUINO_LOOP_STACK_SIZE;
|
||||
}
|
||||
|
||||
void loopTask(void *pvParameters)
|
||||
{
|
||||
setup();
|
||||
for(;;) {
|
||||
if(loopTaskWDTEnabled) esp_task_wdt_reset();
|
||||
loop();
|
||||
if (serialEventRun) serialEventRun();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void app_main() {
|
||||
initArduino();
|
||||
xTaskCreateUniversal(loopTask, "loopTask", getArduinoLoopTaskStackSize(), NULL, 1, &loopTaskHandle, ARDUINO_RUNNING_CORE);
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "rds.h"
|
||||
#include "constants.h"
|
||||
#include <TimeLib.h>
|
||||
#include "utils.h"
|
||||
|
||||
String HexStringold;
|
||||
@@ -513,7 +512,7 @@ void showPS() {
|
||||
}
|
||||
|
||||
void showCT() {
|
||||
char timeStr[16];
|
||||
char timeStr[32];
|
||||
char dateStr[9];
|
||||
time_t t = rtc.getEpoch();
|
||||
|
||||
@@ -532,8 +531,8 @@ void showCT() {
|
||||
else if (hour > 12) hour -= 12;
|
||||
}
|
||||
|
||||
String ampm = (localtm->tm_hour >= 12) ? "PM" : "AM";
|
||||
snprintf(timeStr, sizeof(timeStr), "%d:%02d %s", hour, localtm->tm_min, ampm.c_str());
|
||||
const char* ampm = (localtm->tm_hour >= 12) ? "PM" : "AM";
|
||||
snprintf(timeStr, sizeof(timeStr), "%d:%02d %.2s", hour, localtm->tm_min, ampm);
|
||||
} else {
|
||||
int hour = localtm->tm_hour;
|
||||
if (hour < 0 || hour > 23) hour = 0;
|
||||
|
||||
35
src/rtc.cpp
35
src/rtc.cpp
@@ -14,23 +14,8 @@ void timeToDateTime(time_t t, struct RX8010SJ::DateTime* dateTime) {
|
||||
dateTime->hour = timeinfo->tm_hour;
|
||||
dateTime->dayOfWeek = (timeinfo->tm_wday + 6) % 7;
|
||||
dateTime->dayOfMonth = timeinfo->tm_mday;
|
||||
dateTime->month = timeinfo->tm_mon + 1; // tm_mon is 0-11, convert to 1-12
|
||||
dateTime->year = (timeinfo->tm_year + 1900) % 100; // Get last 2 digits
|
||||
}
|
||||
|
||||
time_t timegm(struct tm *tm) {
|
||||
// https://linux.die.net/man/3/timegm
|
||||
time_t ret;
|
||||
char *tz;
|
||||
|
||||
tz = getenv("TZ");
|
||||
setenv("TZ", "", 1);
|
||||
tzset();
|
||||
ret = mktime(tm);
|
||||
if (tz) setenv("TZ", tz, 1);
|
||||
else unsetenv("TZ");
|
||||
tzset();
|
||||
return ret;
|
||||
dateTime->month = timeinfo->tm_mon + 1;
|
||||
dateTime->year = (timeinfo->tm_year + 1900) % 100;
|
||||
}
|
||||
|
||||
time_t dateTimeToTime(const struct RX8010SJ::DateTime* dateTime) {
|
||||
@@ -42,17 +27,19 @@ time_t dateTimeToTime(const struct RX8010SJ::DateTime* dateTime) {
|
||||
timeinfo.tm_mon = dateTime->month - 1;
|
||||
timeinfo.tm_year = dateTime->year + 100;
|
||||
timeinfo.tm_isdst = 0;
|
||||
return timegm(&timeinfo);
|
||||
return mktime(&timeinfo);
|
||||
}
|
||||
|
||||
void sync_to_rx_rtc(int32_t offset) {
|
||||
if(!rx_rtc_avail) return;
|
||||
RX8010SJ::DateTime rx_currenttime = RX8010SJ::DateTime();
|
||||
timeToDateTime(rtc.getEpoch() + offset, &rx_currenttime);
|
||||
rx_rtc.writeDateTime(rx_currenttime);
|
||||
}
|
||||
void sync_from_rx_rtc(int32_t offset) {
|
||||
if(!rx_rtc_avail) return;
|
||||
RX8010SJ::DateTime dateTime = rx_rtc.readDateTime();
|
||||
rtc.setTime(dateTimeToTime(&dateTime) + offset);
|
||||
}
|
||||
|
||||
void set_time(time_t time) {
|
||||
rtc.setTime(time);
|
||||
if(!rx_rtc_avail) return;
|
||||
RX8010SJ::DateTime rx_currenttime = RX8010SJ::DateTime();
|
||||
timeToDateTime(time, &rx_currenttime);
|
||||
rx_rtc.writeDateTime(rx_currenttime);
|
||||
}
|
||||
Reference in New Issue
Block a user