libsstvenc
Asynchronous Analogue SSTV encoder
Loading...
Searching...
No Matches
sstvmod.c
Go to the documentation of this file.
1
6/*
7 * © Stuart Longland VK4MSL
8 * SPDX-License-Identifier: MIT
9 */
10
11#include <libsstvenc/sstvfreq.h>
12#include <libsstvenc/sstvmod.h>
13
14void sstvenc_modulator_init(struct sstvenc_mod* const mod,
15 const struct sstvenc_mode* mode,
16 const char* fsk_id, const uint8_t* framebuffer,
17 double rise_time, double fall_time,
18 uint32_t sample_rate, uint8_t time_unit) {
19 /* Initialise the data structures */
20 sstvenc_encoder_init(&(mod->enc), mode, fsk_id, framebuffer);
21 sstvenc_osc_init(&(mod->osc), 1.0, SSTVENC_FREQ_SYNC, 0.0,
22 sample_rate);
23 sstvenc_ps_init(&(mod->ps), 1.0, rise_time, INFINITY, fall_time,
24 sample_rate, time_unit);
25
26 /* Clear the state machine */
27 mod->total_samples = 0;
28 mod->total_ns = 0;
29 mod->remaining = 0;
30}
31
36static void
38 sstvenc_ps_compute(&(mod->ps));
39 mod->osc.amplitude = mod->ps.output;
40 sstvenc_osc_compute(&(mod->osc));
41}
42
46static void sstvenc_modulator_next_tone(struct sstvenc_mod* const mod) {
47 while (mod->enc.phase != SSTVENC_ENCODER_PHASE_DONE) {
48 const struct sstvenc_encoder_pulse* pulse
50
51 if (pulse) {
52 /* Update the oscillator frequency */
54 pulse->frequency);
55
56 /* Figure out time duration in samples */
58 pulse->duration_ns, mod->osc.sample_rate,
60
61 /* Total up time and sample count */
62 mod->total_samples += mod->remaining;
63 mod->total_ns += pulse->duration_ns;
64
65 /* Sanity check timing, adjust for any
66 * slippage */
67 uint64_t expected_total_samples
69 mod->total_ns, mod->osc.sample_rate,
71 if (expected_total_samples > mod->total_samples) {
72 /*
73 * Rounding error has caused a slip,
74 * add samples to catch up.
75 */
76 uint64_t diff = expected_total_samples
77 - mod->total_samples;
78 mod->remaining += diff;
79 mod->total_samples += diff;
80 }
81 return;
82 }
83 }
84}
85
90static void
92 sstvenc_ps_compute(&(mod->ps));
93 mod->osc.amplitude = mod->ps.output;
94
96 /* We're done */
97 if (mod->ps.phase != SSTVENC_PS_PHASE_FALL) {
98 sstvenc_ps_advance(&(mod->ps));
99 }
100 return;
101 }
102
103 if (mod->remaining == 0) {
105 }
106
107 if (mod->remaining > 0) {
108 /* Compute the next oscillator output sample */
109 sstvenc_osc_compute(&(mod->osc));
110 mod->remaining--;
111 }
112}
113
118static void
120 sstvenc_ps_compute(&(mod->ps));
121 mod->osc.amplitude = mod->ps.output;
122 sstvenc_osc_compute(&(mod->osc));
123}
124
125void sstvenc_modulator_compute(struct sstvenc_mod* const mod) {
126 switch (mod->ps.phase) {
129 /* Rising initial pulse */
131 break;
133 /* SSTV encoding state */
135 break;
137 /* Falling final pulse */
139 break;
140 default:
141 /* We're done */
142 mod->osc.output = 0.0;
143 break;
144 }
145}
146
148 double* buffer, size_t buffer_sz) {
149 size_t written_sz = 0;
150
151 while ((buffer_sz > 0) && (mod->ps.phase < SSTVENC_PS_PHASE_DONE)) {
153
154 buffer[0] = mod->osc.output;
155 buffer++;
156 buffer_sz--;
157
158 written_sz++;
159 }
160
161 return written_sz;
162}
163
uint32_t sample_rate
Definition oscillator.h:55
void sstvenc_osc_init(struct sstvenc_oscillator *const osc, double amplitude, double frequency, double offset, uint32_t sample_rate)
Definition oscillator.c:42
void sstvenc_osc_set_frequency(struct sstvenc_oscillator *const osc, double frequency)
Definition oscillator.c:33
void sstvenc_osc_compute(struct sstvenc_oscillator *const osc)
Definition oscillator.c:52
#define SSTVENC_PS_PHASE_HOLD
Definition pulseshape.h:58
#define SSTVENC_PS_PHASE_FALL
Definition pulseshape.h:67
#define SSTVENC_PS_PHASE_INIT
Definition pulseshape.h:35
#define SSTVENC_PS_PHASE_RISE
Definition pulseshape.h:44
#define SSTVENC_PS_PHASE_DONE
Definition pulseshape.h:75
void sstvenc_ps_advance(struct sstvenc_pulseshape *const ps)
Definition pulseshape.c:56
void sstvenc_ps_compute(struct sstvenc_pulseshape *const ps)
Definition pulseshape.c:63
void sstvenc_ps_init(struct sstvenc_pulseshape *const ps, double amplitude, double rise_time, double hold_time, double fall_time, uint32_t sample_rate, uint8_t time_unit)
Definition pulseshape.c:28
uint64_t total_ns
Definition sstvmod.h:48
uint32_t remaining
Definition sstvmod.h:50
struct sstvenc_oscillator osc
Definition sstvmod.h:42
struct sstvenc_pulseshape ps
Definition sstvmod.h:44
struct sstvenc_encoder enc
Definition sstvmod.h:40
uint64_t total_samples
Definition sstvmod.h:46
void sstvenc_modulator_init(struct sstvenc_mod *const mod, const struct sstvenc_mode *mode, const char *fsk_id, const uint8_t *framebuffer, double rise_time, double fall_time, uint32_t sample_rate, uint8_t time_unit)
Definition sstvmod.c:14
void sstvenc_modulator_compute(struct sstvenc_mod *const mod)
Definition sstvmod.c:125
static void sstvenc_modulator_next_rise_sample(struct sstvenc_mod *const mod)
Definition sstvmod.c:37
size_t sstvenc_modulator_fill_buffer(struct sstvenc_mod *const mod, double *buffer, size_t buffer_sz)
Definition sstvmod.c:147
static void sstvenc_modulator_next_hold_sample(struct sstvenc_mod *const mod)
Definition sstvmod.c:91
static void sstvenc_modulator_next_tone(struct sstvenc_mod *const mod)
Definition sstvmod.c:46
static void sstvenc_modulator_next_fall_sample(struct sstvenc_mod *const mod)
Definition sstvmod.c:119
#define SSTVENC_ENCODER_PHASE_DONE
Definition sstv.h:80
void sstvenc_encoder_init(struct sstvenc_encoder *const enc, const struct sstvenc_mode *mode, const char *fsk_id, const uint8_t *framebuffer)
Definition sstv.c:392
uint8_t phase
Definition sstv.h:180
const struct sstvenc_encoder_pulse * sstvenc_encoder_next_pulse(struct sstvenc_encoder *const enc)
Definition sstv.c:1032
#define SSTVENC_FREQ_SYNC
Definition sstvfreq.h:19
#define SSTVENC_TS_UNIT_NANOSECONDS
Definition timescale.h:39
uint32_t sstvenc_ts_unit_to_samples(double time, uint32_t sample_rate, uint8_t unit)
Definition timescale.c:46