0
1
mirror of https://github.com/radio95-rnt/fm95.git synced 2026-02-26 19:23:51 +01:00
This commit is contained in:
2025-03-09 16:14:27 +01:00
parent 8f5fe50d65
commit 554ede3f75
2 changed files with 92 additions and 12 deletions

View File

@@ -1,5 +1,5 @@
{ {
"port": 13452, "port": 13452,
"time": 1741524942188, "time": 1741529730555,
"version": "0.0.3" "version": "0.0.3"
} }

View File

@@ -4,6 +4,7 @@
#include <time.h> #include <time.h>
#include <signal.h> #include <signal.h>
#include <string.h> #include <string.h>
#include <math.h>
#define buffer_maxlength 2048 #define buffer_maxlength 2048
#define buffer_tlength_fragsize 2048 #define buffer_tlength_fragsize 2048
@@ -33,6 +34,13 @@
#define REDUCED_AMPLITUDE 0.15f // Reduced to 15% of normal amplitude during pulses #define REDUCED_AMPLITUDE 0.15f // Reduced to 15% of normal amplitude during pulses
#define BIT_LENGTH 1000 // 1 second per bit #define BIT_LENGTH 1000 // 1 second per bit
// DSSS Parameters
#define DSSS_START_MS 200 // DSSS starts at 200ms into the second
#define DSSS_DURATION_MS 793 // DSSS duration is 793ms
#define PHASE_SHIFT 15.6 // Phase shift in degrees (±15.6°)
#define CHIPS_PER_BIT 512 // Number of chips per bit
#define CHIP_CYCLES 120 // Each chip spans 120 cycles
volatile sig_atomic_t to_run = 1; volatile sig_atomic_t to_run = 1;
volatile sig_atomic_t transmitting = 0; volatile sig_atomic_t transmitting = 0;
volatile int bit_position = 0; volatile int bit_position = 0;
@@ -41,12 +49,31 @@ volatile int test_mode = 0; // 0 = normal, 1 = test mode
// DCF77 bits array (59 bits, indexed 0-58) // DCF77 bits array (59 bits, indexed 0-58)
volatile int dcf77_bits[60]; // 60th position is for the 1-second pause volatile int dcf77_bits[60]; // 60th position is for the 1-second pause
// LFSR state for DSSS
unsigned int lfsr = 0;
static void stop(int signum) { static void stop(int signum) {
(void)signum; (void)signum;
printf("\nReceived stop signal.\n"); printf("\nReceived stop signal.\n");
to_run = 0; to_run = 0;
} }
// Generate next chip from LFSR
unsigned int generate_chip() {
unsigned int chip = lfsr & 1;
lfsr >>= 1;
if (chip || !lfsr)
lfsr ^= 0x110;
return chip;
}
// Reset LFSR state at the beginning of each second
void reset_lfsr() {
lfsr = 0;
}
// Helper function to determine if a given time is in DST for CET // Helper function to determine if a given time is in DST for CET
int is_cet_dst(struct tm *tm_time) { int is_cet_dst(struct tm *tm_time) {
// CET DST rules: starts last Sunday of March at 2:00, ends last Sunday of October at 3:00 // CET DST rules: starts last Sunday of March at 2:00, ends last Sunday of October at 3:00
@@ -78,6 +105,7 @@ int is_cet_dst(struct tm *tm_time) {
return 0; // Not in DST return 0; // Not in DST
} }
int is_timezone_change_soon() { int is_timezone_change_soon() {
time_t now, in_an_hour; time_t now, in_an_hour;
struct tm cet_now, cet_later; struct tm cet_now, cet_later;
@@ -306,7 +334,7 @@ int main(int argc, char **argv) {
// #endregion // #endregion
if(test_mode) { if(test_mode) {
time_t now = time(NULL) + offset; time_t now = time(NULL) + offset + 60;
calculate_dcf77_bits(now, (int *)dcf77_bits); calculate_dcf77_bits(now, (int *)dcf77_bits);
print_dcf77_bits((int *)dcf77_bits); print_dcf77_bits((int *)dcf77_bits);
return 0; return 0;
@@ -318,6 +346,7 @@ int main(int argc, char **argv) {
printf(" Sample rate: %d Hz\n", sample_rate); printf(" Sample rate: %d Hz\n", sample_rate);
printf(" Volume: %.2f\n", master_volume); printf(" Volume: %.2f\n", master_volume);
printf(" Time offset: %d seconds\n", offset); printf(" Time offset: %d seconds\n", offset);
printf(" Phase modulation: +/- %.1f degrees\n", PHASE_SHIFT);
// #region Setup devices // #region Setup devices
pa_sample_spec mono_format = { pa_sample_spec mono_format = {
@@ -379,6 +408,17 @@ int main(int argc, char **argv) {
int pulse_0_samples = (int)((PULSE_0_DURATION / 1000.0) * sample_rate); int pulse_0_samples = (int)((PULSE_0_DURATION / 1000.0) * sample_rate);
int pulse_1_samples = (int)((PULSE_1_DURATION / 1000.0) * sample_rate); int pulse_1_samples = (int)((PULSE_1_DURATION / 1000.0) * sample_rate);
// DSSS parameters
int dsss_start_samples = (int)((DSSS_START_MS / 1000.0) * sample_rate);
int dsss_duration_samples = (int)((DSSS_DURATION_MS / 1000.0) * sample_rate);
int dsss_end_samples = dsss_start_samples + dsss_duration_samples;
float phase_shift_rad = (PHASE_SHIFT * M_PI) / 180.0; // Convert degrees to radians
// For tracking chip generation
int current_chip_count = 0;
int current_cycle_count = 0;
int in_dsss_period = 0;
printf("DCF77 encoder ready.\n"); printf("DCF77 encoder ready.\n");
printf("Will transmit time signal continuously.\n"); printf("Will transmit time signal continuously.\n");
@@ -388,7 +428,7 @@ int main(int argc, char **argv) {
memset(output, 0, sizeof(output)); memset(output, 0, sizeof(output));
// Get current time // Get current time
time_t now = time(NULL) + offset; time_t now = time(NULL) + offset + 60; // Next minute
struct tm *t = gmtime(&now); struct tm *t = gmtime(&now);
int second = t->tm_sec; int second = t->tm_sec;
@@ -415,6 +455,11 @@ int main(int argc, char **argv) {
if (second != current_second) { if (second != current_second) {
current_second = second; current_second = second;
// Reset the LFSR at the start of each second for DSSS
reset_lfsr();
current_chip_count = 0;
current_cycle_count = 0;
// Update the bit position at the start of each second // Update the bit position at the start of each second
if (transmitting) { if (transmitting) {
if (bit_position < 59) { if (bit_position < 59) {
@@ -436,17 +481,52 @@ int main(int argc, char **argv) {
// Generate the DCF77 signal // Generate the DCF77 signal
for (int i = 0; i < BUFFER_SIZE; i++) { for (int i = 0; i < BUFFER_SIZE; i++) {
// Get base carrier signal // Calculate milliseconds within the current second
float carrier = get_oscillator_sin_sample(&osc); ms_within_second = (int)((elapsed_samples * 1000.0) / sample_rate);
// Get the current bit (between 0-58)
int current_bit = bit_position > 0 ? bit_position - 1 : 59;
// Determine if we're in the DSSS period (between 200ms and 993ms)
in_dsss_period = (elapsed_samples >= dsss_start_samples &&
elapsed_samples < dsss_end_samples);
// Base carrier signal (will be phase-shifted if in DSSS period)
float phase_offset = 0.0;
// Apply DSSS if in the appropriate time window
if (in_dsss_period && transmitting) {
// Generate a chip every CHIP_CYCLES carrier cycles
if (current_cycle_count == 0) {
if (current_chip_count < CHIPS_PER_BIT) {
// Generate the next chip
unsigned int chip = generate_chip();
// XOR the chip with the current bit value
unsigned int modulated_chip = chip ^ dcf77_bits[current_bit];
// Set phase shift based on the modulated chip
if (modulated_chip == 0) {
phase_offset = phase_shift_rad; // +15.6 degrees
} else {
phase_offset = -phase_shift_rad; // -15.6 degrees
}
current_chip_count++;
}
}
// Update cycle counter within each chip
current_cycle_count = (current_cycle_count + 1) % CHIP_CYCLES;
}
// Get carrier signal with phase offset if needed
float t = osc.phase + phase_offset;
float carrier = sin(t);
advance_oscillator(&osc);
if (transmitting) { if (transmitting) {
// Calculate milliseconds within the current second // Determine amplitude based on AM modulation pattern
ms_within_second = (int)((elapsed_samples * 1000.0) / sample_rate);
// Get the current bit (between 0-58)
int current_bit = bit_position > 0 ? bit_position - 1 : 59;
// Determine if we should output reduced amplitude
if ((dcf77_bits[current_bit] == 0 && ms_within_second < PULSE_0_DURATION) || if ((dcf77_bits[current_bit] == 0 && ms_within_second < PULSE_0_DURATION) ||
(dcf77_bits[current_bit] == 1 && ms_within_second < PULSE_1_DURATION)) { (dcf77_bits[current_bit] == 1 && ms_within_second < PULSE_1_DURATION)) {
// Reduced amplitude during pulse // Reduced amplitude during pulse